# Copyright 2006 James Tauber and contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# iteration from Bob Ippolito's Iteration in JavaScript

# must declare import _before_ importing sys

from __pyjamas__ import INT, JS, setCompilerOptions, debugger

setCompilerOptions("noDebug", "noBoundMethods", "noDescriptors", "noAttributeChecking", "noSourceTracking", "noLineTracking", "noStoreSource")

# Patching of the standard javascript Array object
# This makes it imposible to use for (k in Array())
JS("""
if (typeof Array.prototype.indexOf != 'function') {
    Array.prototype.indexOf = function(elt /*, from*/) {
        var len = this.length >>> 0;

        var from = Number(arguments[1]) || 0;
        from = (from < 0)
                ? Math.ceil(from)
                : Math.floor(from);
        if (from < 0)
            from += len;

        for (; from < len; from++) {
            if (from in this &&
                this[from] === elt)
                return from;
        }
        return -1;
    };
};
""")

# Patching of the standard javascript RegExp
JS("""
RegExp.prototype.Exec = function(pat) {
    var m = this.exec(pat);
    if (m !== null) {
        var len = m.length >>> 0;
        for (var i = 0; i < len; i++) {
            if (typeof(m[i]) == "undefined")
                m[i] = null;
        }
    }
    return m;
};
""")

JS("""
@{{platform}} = $pyjs.platform;
@{{sys}} = null;
@{{dynamic}} = null;

var $max_float_int = 1;
for (var i = 0; i < 1000; i++) {
    $max_float_int *= 2;
    if ($max_float_int + 1 == $max_float_int) {
        break;
    }
}
var $max_int = 0x7fffffff;
var $min_int = -0x80000000;

var $radix_regex = [
    /^$/i,                  //  0
    /^a/i,                  //  1
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[01]+ *$/i,     //  2
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-2]+ *$/i,    //  3
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-3]+ *$/i,    //  4
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-4]+ *$/i,    //  5
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-5]+ *$/i,    //  6
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-6]+ *$/i,    //  7
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-7]+ *$/i,    //  8
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-8]+ *$/i,    //  9
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9]+ *$/i,    // 10
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a]+ *$/i,   // 11
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9ab]+ *$/i,  // 12
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-c]+ *$/i, // 13
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-d]+ *$/i, // 14
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-e]+ *$/i, // 15
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-f]+ *$/i, // 16
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-g]+ *$/i, // 17
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-h]+ *$/i, // 18
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-i]+ *$/i, // 19
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-j]+ *$/i, // 20
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-k]+ *$/i, // 21
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-l]+ *$/i, // 22
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-m]+ *$/i, // 23
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-n]+ *$/i, // 24
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-o]+ *$/i, // 25
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-p]+ *$/i, // 26
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-q]+ *$/i, // 27
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-r]+ *$/i, // 28
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-s]+ *$/i, // 29
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-t]+ *$/i, // 30
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-u]+ *$/i, // 31
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-v]+ *$/i, // 32
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-w]+ *$/i, // 33
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-x]+ *$/i, // 34
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-y]+ *$/i, // 35
    /^[\\t\\n\\x0b\\x0c\\r ]*-? *[0-9a-z]+ *$/i  // 36
];


/**
 * create the __mro__ for a class
 */
function mro_merge(seqs) {
    var res = new Array();
    var i = 0;
    var cand = null;
    function resolve_error(candidates) {
        @{{raise}}($new(@{{TypeError}}, B$str("Cannot create a consistent method resolution order (MRO) for bases " + candidates[0].__name__ + ", "+ candidates[1].__name__)));
    }
    for (;;) {
        var nonemptyseqs = new Array();
        for (var j = 0; j < seqs.length; j++) {
            if (seqs[j].length > 0) nonemptyseqs.push(seqs[j]);
        }
        if (nonemptyseqs.length == 0) return res;
        i++;
        var candidates = new Array();
        for (var j = 0; j < nonemptyseqs.length; j++) {
            cand = nonemptyseqs[j][0];
            candidates.push(cand);
            var nothead = new Array();
            for (var k = 0; k < nonemptyseqs.length; k++) {
                for (var m = 1; m < nonemptyseqs[k].length; m++) {
                    if (cand === nonemptyseqs[k][m]) {
                        nothead.push(nonemptyseqs[k]);
                    }
                }
            }
            if (nothead.length != 0)
                cand = null; // reject candidate
            else
                break;
        }
        if (cand == null) {
            resolve_error(candidates);
        }
        res.push(cand);
        for (var j = 0; j < nonemptyseqs.length; j++) {
            if (nonemptyseqs[j][0] === cand) {
                nonemptyseqs[j].shift();
            }
        }
    }
}

/**
 * Initial type function
 * will be used before definition of tuple type
 *
 * clsname : javascript string with class name
 * bases: javascript array with base classes
 * dict: javascript object
 * module: module object (i.e. namespace)
 * Note
 */
function tmp_type(module, clsname, bases, dict) {
    var cls, mro = new Array();
    if (module !== m$) {
        debugger;
    }
    cls = function () {
        var args = Array.prototype.slice.call(arguments);
        if (args.length >= 3) {
            var len = args.length;
            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                return $newext.apply(this, [arguments.callee].concat(args));
            }
        }
        return $new.apply(this, [arguments.callee].concat(args));
};
    cls['$inst'] = false;
    cls['__name__'] = clsname;
    cls['__bases__'] = bases;
    for (var i = 0; i < bases.length; i++) {
        mro.push(new Array().concat(bases[i].__mro__));
    }
    cls['__mro__'] = [cls].concat(mro_merge(mro));
    cls['$dict'] = {};
    var __module__ = typeof module['$dict'] != "undefined" ? module['$dict']['__name__'] : module['__name__'];
    if (typeof __module__ != "undefined") {
        cls['$dict']['__module__'] = __module__;
    }
    cls['__slots__'] = [];
    cls['__dict__'] = {
        '__object': cls['$dict']
    };
    cls.toString = function () { return "<class " + clsname + ">";};
    return cls;
}

/**
 * builtin type function
 *
 * clsname : javascript string with class name
 * bases: tuple with base classes
 * dict: proxydict instance
 * module: module object (i.e. namespace)
 */
function type(module, clsname, bases, dict, slots) {
    var cls,
        mro$ = new Array(),
        _bases = bases;
        cls = function () {
            var args = Array.prototype.slice.call(arguments);
            if (args.length >= 3) {
                var len = args.length;
                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                    return $newext.apply(this, [arguments.callee].concat(args));
                }
            }
            return $new.apply(this, [arguments.callee].concat(args));
    };
    cls['$inst'] = false;
    cls['__name__'] = typeof clsname == "string" ? B$str(clsname) : clsname;
    if (bases instanceof Array) {
        cls['__bases__'] = B$tuple(bases);
    } else {
        cls['__bases__'] = bases;
        _bases = bases['__array'];
    }
    if (typeof dict['mro'] != "undefined") {
        // The mro method (?) exists. Use that.
        // TODO
        @{{raise}}(@{{NotImplemented}});
    } else {
        for (var i = 0; i < _bases.length; i++) {
            mro$.push(new Array().concat(_bases[i].__mro__));
        }
        cls['__mro__'] = [cls].concat(mro_merge(mro$));
    }
    cls['$dict'] = {};
    if (module['__class__'] !== @{{module}}) {
        debugger;
    }
    var __module__ = typeof module['$dict'] != "undefined" ? module['$dict']['__name__'] : module['__name__'];
    if (typeof __module__ != "undefined") {
        cls['$dict']['__module__'] = __module__;
    }
    if (typeof dict != "undefined" && dict['__class__'] === @{{dict}}) {
        for (var k in dict.__object) {
            cls['$dict'][k] = dict.__object[k];
        }
    }
    cls['__dict__'] = @{{dictproxy}};
    cls['__dict__']['__object'] = cls['$dict'];
    func(m$, null, cls, '__call__', 3, null, 'args', 'kwargs', null, $newext, true);
    cls['__class__'] = @{{type}};
    if (typeof slots != "undefined") {
        cls['__slots__'] = slots;
    }
    cls.toString = function () { return "<class " + clsname + ">";};
    return cls;
}
@{{B$type}} = type;

_f = @{{fcall}} = function (module, lineno, obj, base /*, args*/) {
    var method = null;
    var rval, f, star = null, dstar = null, named = null, o = obj,
        args = Array.prototype.slice.call(arguments, 4),
        track_len = $pyjs.trackstack.length;
    for (var i = 0; i < args.length; i++) {
        if (typeof args[i] == "undefined") {
            return @{{raise}}($new(@{{TypeError}}, B$str("argument " + i + " is undefined")));
        }
    }
    if (module !== null && lineno !== null) {
        if (module['__class__'] !== @{{module}}) {
            debugger;
        }
        $pyjs.track.lineno = lineno;
        $pyjs.track.module = module;
        $pyjs.trackstack[track_len] = {'lineno': $pyjs.track.lineno, 'module': $pyjs.track.module};
    }
    if (typeof o == "undefined") {
        //debugger;
        //return N$;
        throw "o == 'undefined'";
    }
    for (;;) {
        switch (o['__class__']) {
            case @{{function}}:
                f = o;
                break;
            case @{{instancemethod}}:
                f = o['im_func'];
                if (o['im_self'] !== null){
                    args = [o['im_self']].concat(args);
                } else if (base !== null) {
                    args = [base].concat(args);
                } else if (obj['$inst'] === true) {
                    args = [obj].concat(args);
                } else {
                    if (args.length > 0 && args[0]['$inst'] === true) {
                        // check if args[0].__class__.__mro__ contains im_class
                        var mro = args[0]['__class__']['__mro__'];
                        for (var j = 0; j < mro.length; j++) {
                            if (mro[j] === o['im_class']) {
                                mro = true;
                                break;
                            }
                        }
                        if (mro !== true) {
                            @{{_issubtype}}(o['im_class'], args[0]);
                            return @{{raise}}($new(@{{TypeError}}, B$str(
                                "unbound method " + f.__name__ + "() " +
                                "must be called with " + _typeof(o['im_class']) +
                                " instance as first argument (got " +
                                _typeof(args[0]) + " instance instead)")));
                        }
                        break;
                    }
                    return @{{raise}}($new(@{{TypeError}}, B$str(
                        "unbound method " + f.__name__ + "()" +
                        " must be called with " + _typeof(o['im_class']) +
                        " instance as first argument (got nothing instead)")));
                }
                break;
            default:
                if (typeof o != 'function') {
                    return @{{raise}}($new(@{{TypeError}}, B$str("javascript '" + typeof obj + "' object is not callable")));
                }
                if (typeof o['$inst'] === "boolean") {
                    obj = o;
                    method = '__call__';
                    //o = o['__call__'];
                    o = @{{_getattr}}(obj, method);
                } else if (o['$inst'] === true) {
                    o = @{{_getattr}}(obj, method);
                } else {
                    f = o;
                    break;
                }
                if (typeof o == "undefined") {
                    return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(obj) + "' object is not callable")));
                }
                continue
        }
        break;
    }
    if (typeof f.func_args != "undefined") {
        var n_args = args.length;
        if (dstar === null && args.length < f.func_args.length) {
            // Just add defaults
            var n = f.func_args.length - args.length;
            if (n > 0 && f.func_defaults !== null) {
                if (n > f.func_defaults.length) {
                    args = args.concat(f.func_defaults.slice(0));
                } else {
                    n = f.func_defaults.length - n;
                    args = args.concat(f.func_defaults.slice(n));
                }
            }
        }
        if (f.func_args.length != args.length) {
            if (f.func_starargs !== null && f.func_args.length < args.length) {
                if (f.func_args.length == 0) {
                    star = args;
                    args = [];
                } else {
                    star = args.slice(f.func_args.length);
                    args.splice(f.func_args.length, args.length - f.func_args.length);
                }
                star = B$tuple(star);
            } else if (f.func_defaults === null || f.func_defaults.length == 0) {
                switch (f.func_args.length) {
                    case 0:
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes no arguments (" + n_args + " given)")));
                    case 1:
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes exactly " + f.func_args.length + " argument (" + n_args + " given)")));
                    default:
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes exactly " + f.func_args.length + " arguments (" + n_args + " given)")));
                }
            } else {
                if (f.func_args.length > args.length) {
                    if (f.func_minargs == 1) {
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at least 1 argument (0 given)")));
                    } else {
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at least " + f.func_minargs + " arguments (" + n_args + " given)")));
                    }
                }
                if (f.func_minargs == 1) {
                    @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at most 1 argument (" + n_args + " given)")));
                } else {
                    @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at most " + f.func_minargs + " arguments (" + n_args + " given)")));
                }
            }
        }
        if (f.func_starargs !== null) {
            if (star === null) {
                //star = B$tuple([]);
                star = empty_tuple;
            }
            args.push(star);
        }
        if (module !== null && lineno !== null) {
            if (typeof f._module != "undefined" &&
                f._module !== null &&
                typeof f._lineno != "undefined" &&
                f._lineno !== null) {
                $pyjs.track.module = f._module;
                $pyjs.track.lineno = f._lineno;
            }
        }
        if (dstar !== null) {
            args.push(dstar);
            args.push(null); // no named args
        } else if (f.func_dstarargs !== null) {
            dstar = B$dict();
            args.push(dstar);
            args.push(null); // no named args
        }
    }
    if (typeof obj['$inst'] != "undefined" || typeof obj['func_type'] != "undefined") {
        rval = f.apply(module, args);
    } else {
        // obj is an ordinary javascript object
        rval = f.apply(obj, args);
    }
    if (typeof rval == "undefined") {
        if (typeof f['__name__'] == 'undefined') {
            return N$;
        } else {
            @{{raise}}($new(@{{ValueError}}, B$str("return value of call is undefined")));
        }
    }
    if (module !== null && lineno !== null) {
        $pyjs.track = $pyjs.trackstack[track_len];
        $pyjs.trackstack.splice(track_len, $pyjs.trackstack.length);
        if (typeof $pyjs.track == "undefined" || $pyjs.track.lineno != lineno || $pyjs.track.module !== module) {
            debugger;
        }
    }
    return rval;
};

_fe = @{{fcallext}} = function (module, lineno, obj, base /*, args, star_args, dstar_args, named_args*/) {
    var method = null;
    var rval, f, star = null, dstar = null, named = null, o = obj,
        args = Array.prototype.slice.call(arguments, 4),
        track_len = $pyjs.trackstack.length;
    for (var i = 0; i < args.length; i++) {
        if (typeof args[i] == "undefined") {
            return @{{raise}}($new(@{{TypeError}}, B$str("argument " + i + " is undefined")));
        }
    }
    if (module !== null && lineno !== null) {
        if (module['__class__'] !== @{{module}}) {
            debugger;
        }
        $pyjs.track.lineno = lineno;
        $pyjs.track.module = module;
        $pyjs.trackstack[track_len] = {'lineno': $pyjs.track.lineno, 'module': $pyjs.track.module};
    }
    if (typeof o == "undefined") {
        //debugger;
        //return N$;
        throw "o == 'undefined'";
    }
    for (;;) {
        switch (o['__class__']) {
            case @{{function}}:
                f = o;
                break;
            case @{{instancemethod}}:
                f = o['im_func'];
                if (o['im_self'] !== null){
                    args = [o['im_self']].concat(args);
                } else if (base !== null) {
                    args = [base].concat(args);
                } else if (obj['$inst'] === true) {
                    args = [obj].concat(args);
                } else {
                    if (args.length > 0 && args[0]['$inst'] === true) {
                        // check if args[0].__class__.__mro__ contains im_class
                        var mro = args[0]['__class__']['__mro__'];
                        for (var j = 0; j < mro.length; j++) {
                            if (mro[j] === o['im_class']) {
                                mro = true;
                                break;
                            }
                        }
                        if (mro !== true) {
                            @{{_issubtype}}(o['im_class'], args[0]);
                            return @{{raise}}($new(@{{TypeError}}, B$str(
                                "unbound method " + f.__name__ + "() " +
                                "must be called with " + _typeof(o['im_class']) +
                                " instance as first argument (got " +
                                _typeof(args[0]) + " instance instead)")));
                        }
                        break;
                    }
                    return @{{raise}}($new(@{{TypeError}}, B$str(
                        "unbound method " + f.__name__ + "()" +
                        " must be called with " + _typeof(o['im_class']) +
                        " instance as first argument (got nothing instead)")));
                }
                break;
            default:
                if (typeof o != 'function') {
                    return @{{raise}}($new(@{{TypeError}}, B$str("javascript '" + typeof obj + "' object is not callable")));
                }
                if (typeof o['$inst'] === "boolean") {
                    obj = o;
                    method = '__call__';
                    //o = o['__call__'];
                    o = @{{_getattr}}(obj, method);
                } else if (o['$inst'] === true) {
                    o = @{{_getattr}}(obj, method);
                } else {
                    f = o;
                    break;
                }
                if (typeof o == "undefined") {
                    return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(obj) + "' object is not callable")));
                }
                continue
        }
        break;
    }
    named = args.pop();
    dstar = args.pop();
    star = args.pop();
    if (star !== null) {
        if (star instanceof Array) {
            args = args.concat(star);
        } if (star.__array instanceof Array) {
            args = args.concat(star.__array);
        } else {
            var iter = @{{fcall}}(this, null, @{{iter}}, null, star),
                next = @{{getattr}}(iter, 'next'),
                stopiter = @{{stopiter}},
                v;
            for (;;) {
                @{{stopiter}} = true;
                v = @{{fcall}}(this, null, next, iter);
                @{{stopiter}} = stopiter;
                if (v === @{{StopIter}}) {
                    break;
                }
                args.push(v);
            }
        }
        star = null;
    }
    if (named !== null) {
        var k, d = {};
        k = false;
        for (k in named) {
            d[k] = named[k];
        }
        if (k !== false) {
            if (typeof f.func_args == "undefined") {
                @{{raise}}($new(@{{TypeError}}, B$str("Cannot apply named arguments on javascript function")));
            }
            named = d;
        }
    }
    if (dstar !== null) {
        if (dstar._length == 0) {
            dstar = null;
        } else {
            if (typeof f.func_args == "undefined") {
                @{{raise}}($new(@{{TypeError}}, B$str("Cannot apply dstar args on javascript function")));
            }
            var k, v, d = {};
            if (dstar.__class__ === @{{dict}}) {
                for (var h in dstar.__object_hash) {
                    k = dstar.__object_hash[h]['key'];
                    if (typeof k != "string" && k.__class__ != @{{str}}) {
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() keywords must be strings")));
                    }
                    d[k.valueOf()] = dstar.__object[h];
                }
            } else if (dstar['$inst'] == "undefined") {
                for (var k in dstar) {
                    d[k] = dstar[k];
                }
            } else {
                @{{raise}}($new(@{{TypeError}}, B$str("Invalid dstar_args")));
            }
            dstar = d;
        }
    }
    if (dstar !== null || named !== null) {
        var ndefaults = f.func_defaults ? f.func_defaults.length : 0;
        if (dstar === null) {
            dstar = {};
        } else if (named === null) {
            named = {};
        }
        for (var i = 0; i < f.func_args.length; i++) {
            k = f.func_args[i];
            v = named[k];
            delete named[k];
            if (typeof v == "undefined") {
                v = dstar[k];
                delete dstar[k];
            } else if (typeof dstar[k] != "undefined") {
                @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() got multiple values for keyword argument '" + k + "'")));
            }
            if (typeof v != "undefined") {
                if (i < args.length) {
                    @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() got multiple values for keyword argument '" + k + "'")));
                }
                args[i] = v;
            } else if (i >= args.length) {
                if (i < f.func_minargs) {
                    @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at least " + f.func_minargs + " non-keyword arguments (" + f.func_args.length + " given)")));
                }
                args[i] = f.func_defaults[ndefaults - (f.func_args.length - i)];
            }
        }
        if (f.func_dstarargs === null) {
            for (var k in dstar) {
                @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() got an unexpected keyword argument '" + k + "'")));
            }
        }
        for (k in named) {
            if (typeof dstar[k] != 'undefined') {
                return @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() got multiple values for keyword argument '" + k + "'")));
            }
            dstar[k] = named[k];
        }
        dstar = $new(@{{dict}}, dstar);
    }

    if (typeof f.func_args != "undefined") {
        var n_args = args.length;
        if (dstar === null && args.length < f.func_args.length) {
            // Just add defaults
            var n = f.func_args.length - args.length;
            if (n > 0 && f.func_defaults !== null) {
                if (n > f.func_defaults.length) {
                    args = args.concat(f.func_defaults.slice(0));
                } else {
                    n = f.func_defaults.length - n;
                    args = args.concat(f.func_defaults.slice(n));
                }
            }
        }
        if (f.func_args.length != args.length) {
            if (f.func_starargs !== null && f.func_args.length < args.length) {
                if (f.func_args.length == 0) {
                    star = args;
                    args = [];
                } else {
                    star = args.slice(f.func_args.length);
                    args.splice(f.func_args.length, args.length - f.func_args.length);
                }
                star = B$tuple(star);
            } else if (f.func_defaults === null || f.func_defaults.length == 0) {
                switch (f.func_args.length) {
                    case 0:
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes no arguments (" + n_args + " given)")));
                    case 1:
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes exactly " + f.func_args.length + " argument (" + n_args + " given)")));
                    default:
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes exactly " + f.func_args.length + " arguments (" + n_args + " given)")));
                }
            } else {
                if (f.func_args.length > args.length) {
                    if (f.func_minargs == 1) {
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at least 1 argument (0 given)")));
                    } else {
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at least " + f.func_minargs + " arguments (" + n_args + " given)")));
                    }
                }
                if (f.func_minargs == 1) {
                    @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at most 1 argument (" + n_args + " given)")));
                } else {
                    @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at most " + f.func_minargs + " arguments (" + n_args + " given)")));
                }
            }
        }
        if (f.func_starargs !== null) {
            if (star === null) {
                //star = B$tuple([]);
                star = empty_tuple;
            }
            args.push(star);
        }
        if (module !== null && lineno !== null) {
            if (typeof f._module != "undefined" &&
                f._module !== null &&
                typeof f._lineno != "undefined" &&
                f._lineno !== null) {
                $pyjs.track.module = f._module;
                $pyjs.track.lineno = f._lineno;
            }
        }
        if (dstar !== null) {
            args.push(dstar);
            args.push(null); // no named args
        } else if (f.func_dstarargs !== null) {
            dstar = B$dict();
            args.push(dstar);
            args.push(null); // no named args
        }
    }
    if (typeof obj['$inst'] != "undefined" || typeof obj['func_type'] != "undefined") {
        rval = f.apply(module, args);
    } else {
        // obj is an ordinary javascript object
        rval = f.apply(obj, args);
    }
    if (typeof rval == "undefined") {
        if (typeof f['__name__'] == 'undefined') {
            return N$;
        } else {
            @{{raise}}($new(@{{ValueError}}, B$str("return value of call is undefined")));
        }
    }
    if (module !== null && lineno !== null) {
        $pyjs.track = $pyjs.trackstack[track_len];
        $pyjs.trackstack.splice(track_len, $pyjs.trackstack.length);
        if (typeof $pyjs.track == "undefined" || $pyjs.track.lineno != lineno || $pyjs.track.module !== module) {
            debugger;
        }
    }
    return rval;
};

_m = @{{mcall}} = function (module, lineno, obj, method /*, args*/) {
    var base = null;
    var rval, f, star = null, dstar = null, named = null, o = obj,
        args = Array.prototype.slice.call(arguments, 4),
        track_len = $pyjs.trackstack.length;
    for (var i = 0; i < args.length; i++) {
        if (typeof args[i] == "undefined") {
            return @{{raise}}($new(@{{TypeError}}, B$str("argument " + i + " is undefined")));
        }
    }
    if (module !== null && lineno !== null) {
        if (module['__class__'] !== @{{module}}) {
            debugger;
        }
        $pyjs.track.lineno = lineno;
        $pyjs.track.module = module;
        $pyjs.trackstack[track_len] = {'lineno': $pyjs.track.lineno, 'module': $pyjs.track.module};
    }
    if (typeof o == "undefined") {
        //debugger;
        //return N$;
        throw "o == 'undefined'";
    } else if (method !== null) {
        if (method['$inst'] === true) {
            o = method;
        } else if (typeof o['$inst'] == 'boolean') {
            // as in getattr
            var mro$;
            var attrname, attrnames, ga, mro, _obj = obj;
            if (method instanceof Array) {
                attrnames = method;
            } else {
                attrnames = [method];
            }
            find_attr:
            for (var attri = 0; attri < attrnames.length; attri++) {
                attrname = attrnames[attri];
                if (typeof attrname != 'string') {
                    if (typeof attrname['__s'] != "undefined") {
                        attrname = attrname['__s'];
                    } else {
                        @{{raise}}($new(@{{TypeError}}, B$str("attribute name must be string, not '" + _typeof(attrname) + "'")));
                    }
                }
                o = [][1];
                var mro = _obj['__mro__'];
                var _meth_src = _obj;
                switch (_obj['$inst']) {
                    case true:
                        if (_obj['__class__'] === @{{module}}) {
                            o = _obj['$dict'][attrname];
                            break;
                        } else if (_obj['__class__'] === @{{function}}) {
                            switch (attrname.charAt(0)) {
                                case 'i':
                                case '_':
                                    o = _obj[attrname];
                            }
                            break;
                        }
                        var _noraise$ = @{{noraise}};
                        var ga;
                        mro = _obj['__class__']['__mro__'];
                        for (var mro_i$ = 0; mro_i$ < mro.length - 1; mro_i$++) {
                            var _mro$ = mro[mro_i$];
                            var ga = _mro$['__getattribute__'];
                            if (typeof ga == "undefined") {
                                if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                                    continue;
                                }
                                ga = _mro$['$dict']['__getattribute__'];
                            }
                            if (_obj['__class__']['$inst'] === false && _obj['__class__'] !== @{{module}} && typeof _obj != "undefined" && typeof _obj['$inst'] != "undefined") {
                                switch (ga['__class__']) {
                                    case @{{function}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                        _new_dst$['im_func'] = ga;
                                        _new_dst$['im_self'] = _obj['$inst'] === true ? _obj : null;
                                        ga = _new_dst$;
                                        break;
                                    case @{{staticmethod}}:
                                        ga = ga['im_func'];
                                        break;
                                    case @{{classmethod}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                        _new_dst$['im_func'] = ga['im_func'];
                                        _new_dst$['im_self'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                        ga = _new_dst$;
                                        break;
                                    case @{{bool}}: // Some known to be non-descriptors
                                    case @{{int}}:
                                    case @{{long}}:
                                    case @{{str}}:
                                        break;
                                    default:
                                        // check for __get__ method in ga
                                        if (ga['$inst'] === true) {
                                            var get$ = @{{_getattr}}(ga, '__get__');
                                            if (typeof get$ != 'undefined') {
                                                ga = @{{fcall}}(this, null, get$, ga, _obj, _obj['__class__']);
                                            }
                                        }
                                        break;
                                }
                            }
                            @{{noraise}} = @{{AttributeError}};
                            o = @{{fcall}}(this, null, ga, _mro$, attrname);
                            @{{noraise}} = _noraise$;
                            if (o === @{{AttributeError}}) {
                                o = [][1];
                            }
                            _meth_src = _obj['__class__'];
                            _obj = _obj['__class__'];
                            break;
                        }
                        if (typeof o == "undefined") {
                            if (typeof _obj['$dict'] != "undefined") {
                                o = _obj['$dict'][attrname];
                                if (typeof o != "undefined") {
                                    if (o !== {}[attrname]) {
                                        break;
                                    }
                                    o = [][1];
                                }
                            }
                            switch (attrname.charAt(0)) {
                                case 'i':
                                case '_':
                                    o = _obj[attrname];
                            }
                            if (typeof o != "undefined") {
                                break;
                            }
                        }
                    case false:
                        if (typeof o == "undefined") {
                            var _mro$, ga;
                            if (_obj['$inst'] === true) {
                                _meth_src = _obj['__class__'];
                            } else {
                                switch (attrname.charAt(0)) {
                                    case 'i':
                                    case '_':
                                        o = _obj[attrname];
                                }
                                if (typeof o != "undefined") {
                                    break;
                                }

                            }
                            if (typeof o == "undefined") {
                                for (var mro_i$ = 0; mro_i$ < mro.length; mro_i$++) {
                                    _mro$ = mro[mro_i$];
                                    o = _mro$['$dict'][attrname];
                                    if (typeof o != "undefined") {
                                        if (o !== {}[attrname]) {
                                            break;
                                        }
                                        o = [][1];
                                    }
                                    switch (attrname.charAt(0)) {
                                        case 'i':
                                        case '_':
                                            o = _mro$[attrname];
                                    }
                                    if (typeof o != "undefined") {
                                        break;
                                    }
                                }
                            }
                            if (typeof o == "undefined" && attrname !== '__get__') {
                                for (var mro_i$ = 0; mro_i$ < mro.length - 1; mro_i$++) {
                                    _mro$ = mro[mro_i$];
                                    if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                        continue;
                                    }
                                    ga = _mro$['$dict']['__getattr__'];
                                    if (_obj['__class__']['$inst'] === false && _obj['__class__'] !== @{{module}} && typeof _obj != "undefined" && typeof _obj['$inst'] != "undefined") {
                                        switch (ga['__class__']) {
                                            case @{{function}}:
                                                var _new_dst$ = function ( ) {
                                                    var args = Array.prototype.slice.call(arguments);
                                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                        if (arguments.callee['im_self'] !== null) {
                                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                        }
                                                    }
                                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                                    if (typeof a == "undefined") {
                                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                    }
                                                    if (args.length >= 3) {
                                                        var len = args.length;
                                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                        }
                                                    }
                                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                                _new_dst$['toString'] = function ( ) {
                                                    try {
                                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                    } catch (e) {
                                                    }
                                                    try {
                                                        return "<" + this.__class__.__name__ + " instance>";
                                                    } catch (e) {
                                                    }
                                                    return "<instance>";
                                                };
                                                _new_dst$['$inst'] = true;
                                                if (typeof @{{instancemethod}} == "undefined") {
                                                    debugger;
                                                }
                                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                    _new_dst$['__dict__'] = B$dict();
                                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                                }
                                                _new_dst$['__class__'] = @{{instancemethod}};
                                                _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                                _new_dst$['im_func'] = ga;
                                                _new_dst$['im_self'] = _obj['$inst'] === true ? _obj : null;
                                                ga = _new_dst$;
                                                break;
                                            case @{{staticmethod}}:
                                                ga = ga['im_func'];
                                                break;
                                            case @{{classmethod}}:
                                                var _new_dst$ = function ( ) {
                                                    var args = Array.prototype.slice.call(arguments);
                                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                        if (arguments.callee['im_self'] !== null) {
                                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                        }
                                                    }
                                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                                    if (typeof a == "undefined") {
                                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                    }
                                                    if (args.length >= 3) {
                                                        var len = args.length;
                                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                        }
                                                    }
                                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                                _new_dst$['toString'] = function ( ) {
                                                    try {
                                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                    } catch (e) {
                                                    }
                                                    try {
                                                        return "<" + this.__class__.__name__ + " instance>";
                                                    } catch (e) {
                                                    }
                                                    return "<instance>";
                                                };
                                                _new_dst$['$inst'] = true;
                                                if (typeof @{{instancemethod}} == "undefined") {
                                                    debugger;
                                                }
                                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                    _new_dst$['__dict__'] = B$dict();
                                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                                }
                                                _new_dst$['__class__'] = @{{instancemethod}};
                                                _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                                _new_dst$['im_func'] = ga['im_func'];
                                                _new_dst$['im_self'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                                ga = _new_dst$;
                                                break;
                                            case @{{bool}}: // Some known to be non-descriptors
                                            case @{{int}}:
                                            case @{{long}}:
                                            case @{{str}}:
                                                break;
                                            default:
                                                // check for __get__ method in ga
                                                if (ga['$inst'] === true) {
                                                    var get$ = @{{_getattr}}(ga, '__get__');
                                                    if (typeof get$ != 'undefined') {
                                                        ga = @{{fcall}}(this, null, get$, ga, _obj, _obj['__class__']);
                                                    }
                                                }
                                                break;
                                        }
                                    }
                                    @{{noraise}} = @{{AttributeError}};
                                    o = @{{fcall}}(this, null, ga, _mro$, attrname);
                                    @{{noraise}} = _noraise$;
                                    if (o === @{{AttributeError}}) {
                                        o = [][1];
                                    }
                                    // TODO : unbind o ?
                                    break;
                                }
                            }
                        }
                        break;
                    default:
                        o = _obj[attrname];
                        if (typeof o == "undefined" && typeof _obj['$dict'] != "undefined") {
                            o = _obj['$dict'][attrname];
                        }
                }
                if (typeof o == "undefined") {
                    if (_obj['$inst'] === true && _obj['__class__'] !== @{{module}} && _obj['__class__'] !== @{{function}}) {
                        if (typeof o == "undefined") {
                            if (null === null || typeof null == "undefined") {
                                @{{raise}}($new(@{{AttributeError}}, B$str("'" + _obj['__class__']['__name__'] + "' object has no attribute '" + attrname + "'")));
                            } else {
                                o = null;
                                break find_attr;
                            }
                        }
                    }
                    if (null === null || typeof null == "undefined") {
                        if (_obj['$inst'] === false) {
                            @{{raise}}($new(@{{AttributeError}}, B$str("type object '" + _obj['__name__'] + "' object has no attribute '" + attrname + "'")));
                        }
                        @{{raise}}($new(@{{AttributeError}}, B$str(attrname)));
                    }
                    o = null;
                    break find_attr;
                }
                if (attri == attrnames.length - 1) {
                    if (_meth_src['$inst'] === false && _obj['__class__'] !== @{{module}} && typeof _obj != "undefined" && typeof _obj['$inst'] != "undefined") {
                        switch (o['__class__']) {
                            case @{{function}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                _new_dst$['im_func'] = o;
                                _new_dst$['im_self'] = _obj['$inst'] === true ? _obj : null;
                                o = _new_dst$;
                                break;
                            case @{{staticmethod}}:
                                o = o['im_func'];
                                break;
                            case @{{classmethod}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                _new_dst$['im_func'] = o['im_func'];
                                _new_dst$['im_self'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                o = _new_dst$;
                                break;
                            case @{{bool}}: // Some known to be non-descriptors
                            case @{{int}}:
                            case @{{long}}:
                            case @{{str}}:
                                break;
                            default:
                                // check for __get__ method in o
                                if (o['$inst'] === true) {
                                    var get$ = @{{_getattr}}(o, '__get__');
                                    if (typeof get$ != 'undefined') {
                                        o = @{{fcall}}(this, null, get$, o, _obj, _obj['__class__']);
                                    }
                                }
                                break;
                        }
                    }
                } else {
                    // check for __get__ method in o
                    if (o['$inst'] === true) {
                        var get$ = @{{_getattr}}(o, '__get__');
                        if (typeof get$ != 'undefined') {
                            o = @{{fcall}}(this, null, get$, o, _obj, _obj['__class__']);
                        }
                    }
                }
                obj = _obj;
                _obj = o;
            }
        } else {
            o = o[method];
        }
    }
    for (;;) {
        switch (o['__class__']) {
            case @{{function}}:
                f = o;
                break;
            case @{{instancemethod}}:
                f = o['im_func'];
                if (o['im_self'] !== null){
                    args = [o['im_self']].concat(args);
                } else if (base !== null) {
                    args = [base].concat(args);
                } else if (obj['$inst'] === true) {
                    args = [obj].concat(args);
                } else {
                    if (args.length > 0 && args[0]['$inst'] === true) {
                        // check if args[0].__class__.__mro__ contains im_class
                        var mro = args[0]['__class__']['__mro__'];
                        for (var j = 0; j < mro.length; j++) {
                            if (mro[j] === o['im_class']) {
                                mro = true;
                                break;
                            }
                        }
                        if (mro !== true) {
                            @{{_issubtype}}(o['im_class'], args[0]);
                            return @{{raise}}($new(@{{TypeError}}, B$str(
                                "unbound method " + f.__name__ + "() " +
                                "must be called with " + _typeof(o['im_class']) +
                                " instance as first argument (got " +
                                _typeof(args[0]) + " instance instead)")));
                        }
                        break;
                    }
                    return @{{raise}}($new(@{{TypeError}}, B$str(
                        "unbound method " + f.__name__ + "()" +
                        " must be called with " + _typeof(o['im_class']) +
                        " instance as first argument (got nothing instead)")));
                }
                break;
            default:
                if (typeof o != 'function') {
                    return @{{raise}}($new(@{{TypeError}}, B$str("javascript '" + typeof obj + "' object is not callable")));
                }
                if (typeof o['$inst'] === "boolean") {
                    obj = o;
                    method = '__call__';
                    //o = o['__call__'];
                    o = @{{_getattr}}(obj, method);
                } else if (o['$inst'] === true) {
                    o = @{{_getattr}}(obj, method);
                } else {
                    f = o;
                    break;
                }
                if (typeof o == "undefined") {
                    return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(obj) + "' object is not callable")));
                }
                continue
        }
        break;
    }
    if (typeof f.func_args != "undefined") {
        var n_args = args.length;
        if (dstar === null && args.length < f.func_args.length) {
            // Just add defaults
            var n = f.func_args.length - args.length;
            if (n > 0 && f.func_defaults !== null) {
                if (n > f.func_defaults.length) {
                    args = args.concat(f.func_defaults.slice(0));
                } else {
                    n = f.func_defaults.length - n;
                    args = args.concat(f.func_defaults.slice(n));
                }
            }
        }
        if (f.func_args.length != args.length) {
            if (f.func_starargs !== null && f.func_args.length < args.length) {
                if (f.func_args.length == 0) {
                    star = args;
                    args = [];
                } else {
                    star = args.slice(f.func_args.length);
                    args.splice(f.func_args.length, args.length - f.func_args.length);
                }
                star = B$tuple(star);
            } else if (f.func_defaults === null || f.func_defaults.length == 0) {
                switch (f.func_args.length) {
                    case 0:
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes no arguments (" + n_args + " given)")));
                    case 1:
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes exactly " + f.func_args.length + " argument (" + n_args + " given)")));
                    default:
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes exactly " + f.func_args.length + " arguments (" + n_args + " given)")));
                }
            } else {
                if (f.func_args.length > args.length) {
                    if (f.func_minargs == 1) {
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at least 1 argument (0 given)")));
                    } else {
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at least " + f.func_minargs + " arguments (" + n_args + " given)")));
                    }
                }
                if (f.func_minargs == 1) {
                    @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at most 1 argument (" + n_args + " given)")));
                } else {
                    @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at most " + f.func_minargs + " arguments (" + n_args + " given)")));
                }
            }
        }
        if (f.func_starargs !== null) {
            if (star === null) {
                //star = B$tuple([]);
                star = empty_tuple;
            }
            args.push(star);
        }
        if (module !== null && lineno !== null) {
            if (typeof f._module != "undefined" &&
                f._module !== null &&
                typeof f._lineno != "undefined" &&
                f._lineno !== null) {
                $pyjs.track.module = f._module;
                $pyjs.track.lineno = f._lineno;
            }
        }
        if (dstar !== null) {
            args.push(dstar);
            args.push(null); // no named args
        } else if (f.func_dstarargs !== null) {
            dstar = B$dict();
            args.push(dstar);
            args.push(null); // no named args
        }
    }
    if (typeof obj['$inst'] != "undefined" || typeof obj['func_type'] != "undefined") {
        rval = f.apply(module, args);
    } else {
        // obj is an ordinary javascript object
        rval = f.apply(obj, args);
    }
    if (typeof rval == "undefined") {
        if (typeof f['__name__'] == 'undefined') {
            return N$;
        } else {
            @{{raise}}($new(@{{ValueError}}, B$str("return value of call is undefined")));
        }
    }
    if (module !== null && lineno !== null) {
        $pyjs.track = $pyjs.trackstack[track_len];
        $pyjs.trackstack.splice(track_len, $pyjs.trackstack.length);
        if (typeof $pyjs.track == "undefined" || $pyjs.track.lineno != lineno || $pyjs.track.module !== module) {
            debugger;
        }
    }
    return rval;
};

_me = @{{mcallext}} = function (module, lineno, obj, method /*, args, star_args, dstar_args, named_args*/) {
    var base = null;
    var rval, f, star = null, dstar = null, named = null, o = obj,
        args = Array.prototype.slice.call(arguments, 4),
        track_len = $pyjs.trackstack.length;
    for (var i = 0; i < args.length; i++) {
        if (typeof args[i] == "undefined") {
            return @{{raise}}($new(@{{TypeError}}, B$str("argument " + i + " is undefined")));
        }
    }
    if (module !== null && lineno !== null) {
        if (module['__class__'] !== @{{module}}) {
            debugger;
        }
        $pyjs.track.lineno = lineno;
        $pyjs.track.module = module;
        $pyjs.trackstack[track_len] = {'lineno': $pyjs.track.lineno, 'module': $pyjs.track.module};
    }
    if (typeof o == "undefined") {
        //debugger;
        //return N$;
        throw "o == 'undefined'";
    } else if (method !== null) {
        if (method['$inst'] === true) {
            o = method;
        } else if (typeof o['$inst'] == 'boolean') {
            // as in getattr
            var mro$;
            var attrname, attrnames, ga, mro, _obj = obj;
            if (method instanceof Array) {
                attrnames = method;
            } else {
                attrnames = [method];
            }
            find_attr:
            for (var attri = 0; attri < attrnames.length; attri++) {
                attrname = attrnames[attri];
                if (typeof attrname != 'string') {
                    if (typeof attrname['__s'] != "undefined") {
                        attrname = attrname['__s'];
                    } else {
                        @{{raise}}($new(@{{TypeError}}, B$str("attribute name must be string, not '" + _typeof(attrname) + "'")));
                    }
                }
                o = [][1];
                var mro = _obj['__mro__'];
                var _meth_src = _obj;
                switch (_obj['$inst']) {
                    case true:
                        if (_obj['__class__'] === @{{module}}) {
                            o = _obj['$dict'][attrname];
                            break;
                        } else if (_obj['__class__'] === @{{function}}) {
                            switch (attrname.charAt(0)) {
                                case 'i':
                                case '_':
                                    o = _obj[attrname];
                            }
                            break;
                        }
                        var _noraise$ = @{{noraise}};
                        var ga;
                        mro = _obj['__class__']['__mro__'];
                        for (var mro_i$ = 0; mro_i$ < mro.length - 1; mro_i$++) {
                            var _mro$ = mro[mro_i$];
                            var ga = _mro$['__getattribute__'];
                            if (typeof ga == "undefined") {
                                if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                                    continue;
                                }
                                ga = _mro$['$dict']['__getattribute__'];
                            }
                            if (_obj['__class__']['$inst'] === false && _obj['__class__'] !== @{{module}} && typeof _obj != "undefined" && typeof _obj['$inst'] != "undefined") {
                                switch (ga['__class__']) {
                                    case @{{function}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                        _new_dst$['im_func'] = ga;
                                        _new_dst$['im_self'] = _obj['$inst'] === true ? _obj : null;
                                        ga = _new_dst$;
                                        break;
                                    case @{{staticmethod}}:
                                        ga = ga['im_func'];
                                        break;
                                    case @{{classmethod}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                        _new_dst$['im_func'] = ga['im_func'];
                                        _new_dst$['im_self'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                        ga = _new_dst$;
                                        break;
                                    case @{{bool}}: // Some known to be non-descriptors
                                    case @{{int}}:
                                    case @{{long}}:
                                    case @{{str}}:
                                        break;
                                    default:
                                        // check for __get__ method in ga
                                        if (ga['$inst'] === true) {
                                            var get$ = @{{_getattr}}(ga, '__get__');
                                            if (typeof get$ != 'undefined') {
                                                ga = @{{fcall}}(this, null, get$, ga, _obj, _obj['__class__']);
                                            }
                                        }
                                        break;
                                }
                            }
                            @{{noraise}} = @{{AttributeError}};
                            o = @{{fcall}}(this, null, ga, _mro$, attrname);
                            @{{noraise}} = _noraise$;
                            if (o === @{{AttributeError}}) {
                                o = [][1];
                            }
                            _meth_src = _obj['__class__'];
                            _obj = _obj['__class__'];
                            break;
                        }
                        if (typeof o == "undefined") {
                            if (typeof _obj['$dict'] != "undefined") {
                                o = _obj['$dict'][attrname];
                                if (typeof o != "undefined") {
                                    if (o !== {}[attrname]) {
                                        break;
                                    }
                                    o = [][1];
                                }
                            }
                            switch (attrname.charAt(0)) {
                                case 'i':
                                case '_':
                                    o = _obj[attrname];
                            }
                            if (typeof o != "undefined") {
                                break;
                            }
                        }
                    case false:
                        if (typeof o == "undefined") {
                            var _mro$, ga;
                            if (_obj['$inst'] === true) {
                                _meth_src = _obj['__class__'];
                            } else {
                                switch (attrname.charAt(0)) {
                                    case 'i':
                                    case '_':
                                        o = _obj[attrname];
                                }
                                if (typeof o != "undefined") {
                                    break;
                                }

                            }
                            if (typeof o == "undefined") {
                                for (var mro_i$ = 0; mro_i$ < mro.length; mro_i$++) {
                                    _mro$ = mro[mro_i$];
                                    o = _mro$['$dict'][attrname];
                                    if (typeof o != "undefined") {
                                        if (o !== {}[attrname]) {
                                            break;
                                        }
                                        o = [][1];
                                    }
                                    switch (attrname.charAt(0)) {
                                        case 'i':
                                        case '_':
                                            o = _mro$[attrname];
                                    }
                                    if (typeof o != "undefined") {
                                        break;
                                    }
                                }
                            }
                            if (typeof o == "undefined" && attrname !== '__get__') {
                                for (var mro_i$ = 0; mro_i$ < mro.length - 1; mro_i$++) {
                                    _mro$ = mro[mro_i$];
                                    if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                        continue;
                                    }
                                    ga = _mro$['$dict']['__getattr__'];
                                    if (_obj['__class__']['$inst'] === false && _obj['__class__'] !== @{{module}} && typeof _obj != "undefined" && typeof _obj['$inst'] != "undefined") {
                                        switch (ga['__class__']) {
                                            case @{{function}}:
                                                var _new_dst$ = function ( ) {
                                                    var args = Array.prototype.slice.call(arguments);
                                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                        if (arguments.callee['im_self'] !== null) {
                                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                        }
                                                    }
                                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                                    if (typeof a == "undefined") {
                                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                    }
                                                    if (args.length >= 3) {
                                                        var len = args.length;
                                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                        }
                                                    }
                                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                                _new_dst$['toString'] = function ( ) {
                                                    try {
                                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                    } catch (e) {
                                                    }
                                                    try {
                                                        return "<" + this.__class__.__name__ + " instance>";
                                                    } catch (e) {
                                                    }
                                                    return "<instance>";
                                                };
                                                _new_dst$['$inst'] = true;
                                                if (typeof @{{instancemethod}} == "undefined") {
                                                    debugger;
                                                }
                                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                    _new_dst$['__dict__'] = B$dict();
                                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                                }
                                                _new_dst$['__class__'] = @{{instancemethod}};
                                                _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                                _new_dst$['im_func'] = ga;
                                                _new_dst$['im_self'] = _obj['$inst'] === true ? _obj : null;
                                                ga = _new_dst$;
                                                break;
                                            case @{{staticmethod}}:
                                                ga = ga['im_func'];
                                                break;
                                            case @{{classmethod}}:
                                                var _new_dst$ = function ( ) {
                                                    var args = Array.prototype.slice.call(arguments);
                                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                        if (arguments.callee['im_self'] !== null) {
                                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                        }
                                                    }
                                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                                    if (typeof a == "undefined") {
                                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                    }
                                                    if (args.length >= 3) {
                                                        var len = args.length;
                                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                        }
                                                    }
                                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                                _new_dst$['toString'] = function ( ) {
                                                    try {
                                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                    } catch (e) {
                                                    }
                                                    try {
                                                        return "<" + this.__class__.__name__ + " instance>";
                                                    } catch (e) {
                                                    }
                                                    return "<instance>";
                                                };
                                                _new_dst$['$inst'] = true;
                                                if (typeof @{{instancemethod}} == "undefined") {
                                                    debugger;
                                                }
                                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                    _new_dst$['__dict__'] = B$dict();
                                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                                }
                                                _new_dst$['__class__'] = @{{instancemethod}};
                                                _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                                _new_dst$['im_func'] = ga['im_func'];
                                                _new_dst$['im_self'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                                ga = _new_dst$;
                                                break;
                                            case @{{bool}}: // Some known to be non-descriptors
                                            case @{{int}}:
                                            case @{{long}}:
                                            case @{{str}}:
                                                break;
                                            default:
                                                // check for __get__ method in ga
                                                if (ga['$inst'] === true) {
                                                    var get$ = @{{_getattr}}(ga, '__get__');
                                                    if (typeof get$ != 'undefined') {
                                                        ga = @{{fcall}}(this, null, get$, ga, _obj, _obj['__class__']);
                                                    }
                                                }
                                                break;
                                        }
                                    }
                                    @{{noraise}} = @{{AttributeError}};
                                    o = @{{fcall}}(this, null, ga, _mro$, attrname);
                                    @{{noraise}} = _noraise$;
                                    if (o === @{{AttributeError}}) {
                                        o = [][1];
                                    }
                                    // TODO : unbind o ?
                                    break;
                                }
                            }
                        }
                        break;
                    default:
                        o = _obj[attrname];
                        if (typeof o == "undefined" && typeof _obj['$dict'] != "undefined") {
                            o = _obj['$dict'][attrname];
                        }
                }
                if (typeof o == "undefined") {
                    if (_obj['$inst'] === true && _obj['__class__'] !== @{{module}} && _obj['__class__'] !== @{{function}}) {
                        if (typeof o == "undefined") {
                            if (null === null || typeof null == "undefined") {
                                @{{raise}}($new(@{{AttributeError}}, B$str("'" + _obj['__class__']['__name__'] + "' object has no attribute '" + attrname + "'")));
                            } else {
                                o = null;
                                break find_attr;
                            }
                        }
                    }
                    if (null === null || typeof null == "undefined") {
                        if (_obj['$inst'] === false) {
                            @{{raise}}($new(@{{AttributeError}}, B$str("type object '" + _obj['__name__'] + "' object has no attribute '" + attrname + "'")));
                        }
                        @{{raise}}($new(@{{AttributeError}}, B$str(attrname)));
                    }
                    o = null;
                    break find_attr;
                }
                if (attri == attrnames.length - 1) {
                    if (_meth_src['$inst'] === false && _obj['__class__'] !== @{{module}} && typeof _obj != "undefined" && typeof _obj['$inst'] != "undefined") {
                        switch (o['__class__']) {
                            case @{{function}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                _new_dst$['im_func'] = o;
                                _new_dst$['im_self'] = _obj['$inst'] === true ? _obj : null;
                                o = _new_dst$;
                                break;
                            case @{{staticmethod}}:
                                o = o['im_func'];
                                break;
                            case @{{classmethod}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                _new_dst$['im_func'] = o['im_func'];
                                _new_dst$['im_self'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                o = _new_dst$;
                                break;
                            case @{{bool}}: // Some known to be non-descriptors
                            case @{{int}}:
                            case @{{long}}:
                            case @{{str}}:
                                break;
                            default:
                                // check for __get__ method in o
                                if (o['$inst'] === true) {
                                    var get$ = @{{_getattr}}(o, '__get__');
                                    if (typeof get$ != 'undefined') {
                                        o = @{{fcall}}(this, null, get$, o, _obj, _obj['__class__']);
                                    }
                                }
                                break;
                        }
                    }
                } else {
                    // check for __get__ method in o
                    if (o['$inst'] === true) {
                        var get$ = @{{_getattr}}(o, '__get__');
                        if (typeof get$ != 'undefined') {
                            o = @{{fcall}}(this, null, get$, o, _obj, _obj['__class__']);
                        }
                    }
                }
                obj = _obj;
                _obj = o;
            }
        } else {
            o = o[method];
        }
    }
    for (;;) {
        switch (o['__class__']) {
            case @{{function}}:
                f = o;
                break;
            case @{{instancemethod}}:
                f = o['im_func'];
                if (o['im_self'] !== null){
                    args = [o['im_self']].concat(args);
                } else if (base !== null) {
                    args = [base].concat(args);
                } else if (obj['$inst'] === true) {
                    args = [obj].concat(args);
                } else {
                    if (args.length > 0 && args[0]['$inst'] === true) {
                        // check if args[0].__class__.__mro__ contains im_class
                        var mro = args[0]['__class__']['__mro__'];
                        for (var j = 0; j < mro.length; j++) {
                            if (mro[j] === o['im_class']) {
                                mro = true;
                                break;
                            }
                        }
                        if (mro !== true) {
                            @{{_issubtype}}(o['im_class'], args[0]);
                            return @{{raise}}($new(@{{TypeError}}, B$str(
                                "unbound method " + f.__name__ + "() " +
                                "must be called with " + _typeof(o['im_class']) +
                                " instance as first argument (got " +
                                _typeof(args[0]) + " instance instead)")));
                        }
                        break;
                    }
                    return @{{raise}}($new(@{{TypeError}}, B$str(
                        "unbound method " + f.__name__ + "()" +
                        " must be called with " + _typeof(o['im_class']) +
                        " instance as first argument (got nothing instead)")));
                }
                break;
            default:
                if (typeof o != 'function') {
                    return @{{raise}}($new(@{{TypeError}}, B$str("javascript '" + typeof obj + "' object is not callable")));
                }
                if (typeof o['$inst'] === "boolean") {
                    obj = o;
                    method = '__call__';
                    //o = o['__call__'];
                    o = @{{_getattr}}(obj, method);
                } else if (o['$inst'] === true) {
                    o = @{{_getattr}}(obj, method);
                } else {
                    f = o;
                    break;
                }
                if (typeof o == "undefined") {
                    return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(obj) + "' object is not callable")));
                }
                continue
        }
        break;
    }
    named = args.pop();
    dstar = args.pop();
    star = args.pop();
    if (star !== null) {
        if (star instanceof Array) {
            args = args.concat(star);
        } if (star.__array instanceof Array) {
            args = args.concat(star.__array);
        } else {
            var iter = @{{fcall}}(this, null, @{{iter}}, null, star),
                next = @{{getattr}}(iter, 'next'),
                stopiter = @{{stopiter}},
                v;
            for (;;) {
                @{{stopiter}} = true;
                v = @{{fcall}}(this, null, next, iter);
                @{{stopiter}} = stopiter;
                if (v === @{{StopIter}}) {
                    break;
                }
                args.push(v);
            }
        }
        star = null;
    }
    if (named !== null) {
        var k, d = {};
        k = false;
        for (k in named) {
            d[k] = named[k];
        }
        if (k !== false) {
            if (typeof f.func_args == "undefined") {
                @{{raise}}($new(@{{TypeError}}, B$str("Cannot apply named arguments on javascript function")));
            }
            named = d;
        }
    }
    if (dstar !== null) {
        if (dstar._length == 0) {
            dstar = null;
        } else {
            if (typeof f.func_args == "undefined") {
                @{{raise}}($new(@{{TypeError}}, B$str("Cannot apply dstar args on javascript function")));
            }
            var k, v, d = {};
            if (dstar.__class__ === @{{dict}}) {
                for (var h in dstar.__object_hash) {
                    k = dstar.__object_hash[h]['key'];
                    if (typeof k != "string" && k.__class__ != @{{str}}) {
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() keywords must be strings")));
                    }
                    d[k.valueOf()] = dstar.__object[h];
                }
            } else if (dstar['$inst'] == "undefined") {
                for (var k in dstar) {
                    d[k] = dstar[k];
                }
            } else {
                @{{raise}}($new(@{{TypeError}}, B$str("Invalid dstar_args")));
            }
            dstar = d;
        }
    }
    if (dstar !== null || named !== null) {
        var ndefaults = f.func_defaults ? f.func_defaults.length : 0;
        if (dstar === null) {
            dstar = {};
        } else if (named === null) {
            named = {};
        }
        for (var i = 0; i < f.func_args.length; i++) {
            k = f.func_args[i];
            v = named[k];
            delete named[k];
            if (typeof v == "undefined") {
                v = dstar[k];
                delete dstar[k];
            } else if (typeof dstar[k] != "undefined") {
                @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() got multiple values for keyword argument '" + k + "'")));
            }
            if (typeof v != "undefined") {
                if (i < args.length) {
                    @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() got multiple values for keyword argument '" + k + "'")));
                }
                args[i] = v;
            } else if (i >= args.length) {
                if (i < f.func_minargs) {
                    @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at least " + f.func_minargs + " non-keyword arguments (" + f.func_args.length + " given)")));
                }
                args[i] = f.func_defaults[ndefaults - (f.func_args.length - i)];
            }
        }
        if (f.func_dstarargs === null) {
            for (var k in dstar) {
                @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() got an unexpected keyword argument '" + k + "'")));
            }
        }
        for (k in named) {
            if (typeof dstar[k] != 'undefined') {
                return @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() got multiple values for keyword argument '" + k + "'")));
            }
            dstar[k] = named[k];
        }
        dstar = $new(@{{dict}}, dstar);
    }

    if (typeof f.func_args != "undefined") {
        var n_args = args.length;
        if (dstar === null && args.length < f.func_args.length) {
            // Just add defaults
            var n = f.func_args.length - args.length;
            if (n > 0 && f.func_defaults !== null) {
                if (n > f.func_defaults.length) {
                    args = args.concat(f.func_defaults.slice(0));
                } else {
                    n = f.func_defaults.length - n;
                    args = args.concat(f.func_defaults.slice(n));
                }
            }
        }
        if (f.func_args.length != args.length) {
            if (f.func_starargs !== null && f.func_args.length < args.length) {
                if (f.func_args.length == 0) {
                    star = args;
                    args = [];
                } else {
                    star = args.slice(f.func_args.length);
                    args.splice(f.func_args.length, args.length - f.func_args.length);
                }
                star = B$tuple(star);
            } else if (f.func_defaults === null || f.func_defaults.length == 0) {
                switch (f.func_args.length) {
                    case 0:
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes no arguments (" + n_args + " given)")));
                    case 1:
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes exactly " + f.func_args.length + " argument (" + n_args + " given)")));
                    default:
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes exactly " + f.func_args.length + " arguments (" + n_args + " given)")));
                }
            } else {
                if (f.func_args.length > args.length) {
                    if (f.func_minargs == 1) {
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at least 1 argument (0 given)")));
                    } else {
                        @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at least " + f.func_minargs + " arguments (" + n_args + " given)")));
                    }
                }
                if (f.func_minargs == 1) {
                    @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at most 1 argument (" + n_args + " given)")));
                } else {
                    @{{raise}}($new(@{{TypeError}}, B$str(f.__name__ + "() takes at most " + f.func_minargs + " arguments (" + n_args + " given)")));
                }
            }
        }
        if (f.func_starargs !== null) {
            if (star === null) {
                //star = B$tuple([]);
                star = empty_tuple;
            }
            args.push(star);
        }
        if (module !== null && lineno !== null) {
            if (typeof f._module != "undefined" &&
                f._module !== null &&
                typeof f._lineno != "undefined" &&
                f._lineno !== null) {
                $pyjs.track.module = f._module;
                $pyjs.track.lineno = f._lineno;
            }
        }
        if (dstar !== null) {
            args.push(dstar);
            args.push(null); // no named args
        } else if (f.func_dstarargs !== null) {
            dstar = B$dict();
            args.push(dstar);
            args.push(null); // no named args
        }
    }
    if (typeof obj['$inst'] != "undefined" || typeof obj['func_type'] != "undefined") {
        rval = f.apply(module, args);
    } else {
        // obj is an ordinary javascript object
        rval = f.apply(obj, args);
    }
    if (typeof rval == "undefined") {
        if (typeof f['__name__'] == 'undefined') {
            return N$;
        } else {
            @{{raise}}($new(@{{ValueError}}, B$str("return value of call is undefined")));
        }
    }
    if (module !== null && lineno !== null) {
        $pyjs.track = $pyjs.trackstack[track_len];
        $pyjs.trackstack.splice(track_len, $pyjs.trackstack.length);
        if (typeof $pyjs.track == "undefined" || $pyjs.track.lineno != lineno || $pyjs.track.module !== module) {
            debugger;
        }
    }
    return rval;
};

var func = @{{func}} = function (module, lineno, obj, name, type, args, starargs, dstarargs, defaults, def, tobase) {
    // obj is class or local scope
    var o, new_def = def;
    def['__name__'] = B$str(name);
    def['__module__'] = module['__name__'];
    def['func_defaults'] = defaults;
    // non-python func_...
    if (args === null) args = [];
    def['func_args'] = args;
    def['func_starargs'] = starargs;
    def['func_dstarargs'] = dstarargs;
    def['func_minargs'] = (defaults === null? args.length : args.length - defaults.length);
    def['func_type'] = type;
    def['_module'] = module;
    def['_lineno'] = lineno;
    switch (type) {
        case 0:
            // javascript
            break;
        case 2:
            // staticmethod
            new_def = B$__new__(@{{staticmethod}});
            new_def['im_func'] = def;
            // continue to patch the function
        case 1:
            // function
            def['$inst'] = true;
            def['__class__'] = @{{function}};
            def['__slots__'] = [];
            break;
        case 3:
            // classmethod
            new_def = B$__new__(@{{classmethod}});
            new_def['im_func'] = def;
            new_def['im_class'] = obj;
            break;
        case 4:
            // slot wrapper look alike
            // is implemented as a instance method, but can have
            // any type as first argument
            new_def = $new(@{{wrappermethod}}, def, null, obj);
            obj[name] = def;
            return;
            break;
        default:
            // error
            throw "Translator error. Unknown function creation type.";
            break;
    }
    if (typeof obj['$dict'] == "undefined" || tobase === true) {
        obj[name] = new_def;
    } else {
        obj['$dict'][name] = new_def;
    }
    return new_def;
}

var $new = m$['$new'] = @{{$new}} = function (cls/*, args*/) {
    var args = Array.prototype.slice.call(arguments, 1);
    var method$, instance, mro$, module = this['__class__'] === @{{module}} ? this : null;
    method$ = [][1];
    var mro$ = cls['__mro__'];
    var _meth_src = cls;
    switch (cls['$inst']) {
        case true:
            if (cls['__class__'] === @{{module}}) {
                method$ = cls['$dict']['__new__'];
                break;
            } else if (cls['__class__'] === @{{function}}) {
                switch ('__new__'.charAt(0)) {
                    case 'i':
                    case '_':
                        method$ = cls['__new__'];
                }
                break;
            }
            var _noraise$ = @{{noraise}};
            var ga;
            mro$ = cls['__class__']['__mro__'];
            for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                var _mro$ = mro$[mro_i$];
                var ga = _mro$['__getattribute__'];
                if (typeof ga == "undefined") {
                    if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                        continue;
                    }
                    ga = _mro$['$dict']['__getattribute__'];
                }
                if (cls['__class__']['$inst'] === false && cls['__class__'] !== @{{module}} && typeof cls != "undefined" && typeof cls['$inst'] != "undefined") {
                    switch (ga['__class__']) {
                        case @{{function}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                            _new_dst$['im_func'] = ga;
                            _new_dst$['im_self'] = cls['$inst'] === true ? cls : null;
                            ga = _new_dst$;
                            break;
                        case @{{staticmethod}}:
                            ga = ga['im_func'];
                            break;
                        case @{{classmethod}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                            _new_dst$['im_func'] = ga['im_func'];
                            _new_dst$['im_self'] = cls['$inst'] === true ? cls['__class__'] : cls;
                            ga = _new_dst$;
                            break;
                        case @{{bool}}: // Some known to be non-descriptors
                        case @{{int}}:
                        case @{{long}}:
                        case @{{str}}:
                            break;
                        default:
                            // check for __get__ method in ga
                            if (ga['$inst'] === true) {
                                var get$ = @{{_getattr}}(ga, '__get__');
                                if (typeof get$ != 'undefined') {
                                    ga = @{{fcall}}(this, null, get$, ga, cls, cls['__class__']);
                                }
                            }
                            break;
                    }
                }
                @{{noraise}} = @{{AttributeError}};
                method$ = @{{fcall}}(this, null, ga, _mro$, '__new__');
                @{{noraise}} = _noraise$;
                if (method$ === @{{AttributeError}}) {
                    method$ = [][1];
                }
                _meth_src = cls['__class__'];
                cls = cls['__class__'];
                break;
            }
            if (typeof method$ == "undefined") {
                if (typeof cls['$dict'] != "undefined") {
                    method$ = cls['$dict']['__new__'];
                    if (typeof method$ != "undefined") {
                        if (method$ !== {}['__new__']) {
                            break;
                        }
                        method$ = [][1];
                    }
                }
                switch ('__new__'.charAt(0)) {
                    case 'i':
                    case '_':
                        method$ = cls['__new__'];
                }
                if (typeof method$ != "undefined") {
                    break;
                }
            }
        case false:
            if (typeof method$ == "undefined") {
                var _mro$, ga;
                if (cls['$inst'] === true) {
                    _meth_src = cls['__class__'];
                } else {
                    switch ('__new__'.charAt(0)) {
                        case 'i':
                        case '_':
                            method$ = cls['__new__'];
                    }
                    if (typeof method$ != "undefined") {
                        break;
                    }

                }
                if (typeof method$ == "undefined") {
                    for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        method$ = _mro$['$dict']['__new__'];
                        if (typeof method$ != "undefined") {
                            if (method$ !== {}['__new__']) {
                                break;
                            }
                            method$ = [][1];
                        }
                        switch ('__new__'.charAt(0)) {
                            case 'i':
                            case '_':
                                method$ = _mro$['__new__'];
                        }
                        if (typeof method$ != "undefined") {
                            break;
                        }
                    }
                }
                if (typeof method$ == "undefined" && '__new__' !== '__get__') {
                    for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattr__'];
                        if (cls['__class__']['$inst'] === false && cls['__class__'] !== @{{module}} && typeof cls != "undefined" && typeof cls['$inst'] != "undefined") {
                            switch (ga['__class__']) {
                                case @{{function}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                    _new_dst$['im_func'] = ga;
                                    _new_dst$['im_self'] = cls['$inst'] === true ? cls : null;
                                    ga = _new_dst$;
                                    break;
                                case @{{staticmethod}}:
                                    ga = ga['im_func'];
                                    break;
                                case @{{classmethod}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                    _new_dst$['im_func'] = ga['im_func'];
                                    _new_dst$['im_self'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                    ga = _new_dst$;
                                    break;
                                case @{{bool}}: // Some known to be non-descriptors
                                case @{{int}}:
                                case @{{long}}:
                                case @{{str}}:
                                    break;
                                default:
                                    // check for __get__ method in ga
                                    if (ga['$inst'] === true) {
                                        var get$ = @{{_getattr}}(ga, '__get__');
                                        if (typeof get$ != 'undefined') {
                                            ga = @{{fcall}}(this, null, get$, ga, cls, cls['__class__']);
                                        }
                                    }
                                    break;
                            }
                        }
                        @{{noraise}} = @{{AttributeError}};
                        method$ = @{{fcall}}(this, null, ga, _mro$, '__new__');
                        @{{noraise}} = _noraise$;
                        if (method$ === @{{AttributeError}}) {
                            method$ = [][1];
                        }
                        // TODO : unbind method$ ?
                        break;
                    }
                }
            }
            break;
        default:
            method$ = cls['__new__'];
            if (typeof method$ == "undefined" && typeof cls['$dict'] != "undefined") {
                method$ = cls['$dict']['__new__'];
            }
    }
    if (method$ === B$__new__) {
        var instance = function ( ) {
            var args = Array.prototype.slice.call(arguments);
            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                if (arguments.callee['im_self'] !== null) {
                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                }
            }
            var a = @{{_getattr}}(arguments.callee, '__call__');
            if (typeof a == "undefined") {
                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
            }
            if (args.length >= 3) {
                var len = args.length;
                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                }
            }
            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
        }
        instance['toString'] = function ( ) {
            try {
                return @{{mcall}}(this, null, this, '__str__').valueOf();
            } catch (e) {
            }
            try {
                return "<" + this.__class__.__name__ + " instance>";
            } catch (e) {
            }
            return "<instance>";
        };
        instance['$inst'] = true;
        if (typeof cls == "undefined") {
            debugger;
        }
        if (typeof cls['__slots__'] == "undefined" || cls['__slots__'].length > 0) {
            instance['__dict__'] = B$dict();
            instance['$dict'] = instance['__dict__']['__object'];
        }
        instance['__class__'] = cls;
    } else {
        instance = @{{fcall}}.apply(module, [module, null, method$, cls, cls].concat(args));
    }
    if (instance['$inst'] === true) {
        method$ = [][1];
        var mro$ = cls['__mro__'];
        var _meth_src = cls;
        switch (cls['$inst']) {
            case true:
                if (cls['__class__'] === @{{module}}) {
                    method$ = cls['$dict']['__init__'];
                    break;
                } else if (cls['__class__'] === @{{function}}) {
                    switch ('__init__'.charAt(0)) {
                        case 'i':
                        case '_':
                            method$ = cls['__init__'];
                    }
                    break;
                }
                var _noraise$ = @{{noraise}};
                var ga;
                mro$ = cls['__class__']['__mro__'];
                for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                    var _mro$ = mro$[mro_i$];
                    var ga = _mro$['__getattribute__'];
                    if (typeof ga == "undefined") {
                        if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattribute__'];
                    }
                    if (cls['__class__']['$inst'] === false && cls['__class__'] !== @{{module}} && typeof cls != "undefined" && typeof cls['$inst'] != "undefined") {
                        switch (ga['__class__']) {
                            case @{{function}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                _new_dst$['im_func'] = ga;
                                _new_dst$['im_self'] = cls['$inst'] === true ? cls : null;
                                ga = _new_dst$;
                                break;
                            case @{{staticmethod}}:
                                ga = ga['im_func'];
                                break;
                            case @{{classmethod}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                _new_dst$['im_func'] = ga['im_func'];
                                _new_dst$['im_self'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                ga = _new_dst$;
                                break;
                            case @{{bool}}: // Some known to be non-descriptors
                            case @{{int}}:
                            case @{{long}}:
                            case @{{str}}:
                                break;
                            default:
                                // check for __get__ method in ga
                                if (ga['$inst'] === true) {
                                    var get$ = @{{_getattr}}(ga, '__get__');
                                    if (typeof get$ != 'undefined') {
                                        ga = @{{fcall}}(this, null, get$, ga, cls, cls['__class__']);
                                    }
                                }
                                break;
                        }
                    }
                    @{{noraise}} = @{{AttributeError}};
                    method$ = @{{fcall}}(this, null, ga, _mro$, '__init__');
                    @{{noraise}} = _noraise$;
                    if (method$ === @{{AttributeError}}) {
                        method$ = [][1];
                    }
                    _meth_src = cls['__class__'];
                    cls = cls['__class__'];
                    break;
                }
                if (typeof method$ == "undefined") {
                    if (typeof cls['$dict'] != "undefined") {
                        method$ = cls['$dict']['__init__'];
                        if (typeof method$ != "undefined") {
                            if (method$ !== {}['__init__']) {
                                break;
                            }
                            method$ = [][1];
                        }
                    }
                    switch ('__init__'.charAt(0)) {
                        case 'i':
                        case '_':
                            method$ = cls['__init__'];
                    }
                    if (typeof method$ != "undefined") {
                        break;
                    }
                }
            case false:
                if (typeof method$ == "undefined") {
                    var _mro$, ga;
                    if (cls['$inst'] === true) {
                        _meth_src = cls['__class__'];
                    } else {
                        switch ('__init__'.charAt(0)) {
                            case 'i':
                            case '_':
                                method$ = cls['__init__'];
                        }
                        if (typeof method$ != "undefined") {
                            break;
                        }

                    }
                    if (typeof method$ == "undefined") {
                        for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            method$ = _mro$['$dict']['__init__'];
                            if (typeof method$ != "undefined") {
                                if (method$ !== {}['__init__']) {
                                    break;
                                }
                                method$ = [][1];
                            }
                            switch ('__init__'.charAt(0)) {
                                case 'i':
                                case '_':
                                    method$ = _mro$['__init__'];
                            }
                            if (typeof method$ != "undefined") {
                                break;
                            }
                        }
                    }
                    if (typeof method$ == "undefined" && '__init__' !== '__get__') {
                        for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                continue;
                            }
                            ga = _mro$['$dict']['__getattr__'];
                            if (cls['__class__']['$inst'] === false && cls['__class__'] !== @{{module}} && typeof cls != "undefined" && typeof cls['$inst'] != "undefined") {
                                switch (ga['__class__']) {
                                    case @{{function}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                        _new_dst$['im_func'] = ga;
                                        _new_dst$['im_self'] = cls['$inst'] === true ? cls : null;
                                        ga = _new_dst$;
                                        break;
                                    case @{{staticmethod}}:
                                        ga = ga['im_func'];
                                        break;
                                    case @{{classmethod}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                        _new_dst$['im_func'] = ga['im_func'];
                                        _new_dst$['im_self'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                        ga = _new_dst$;
                                        break;
                                    case @{{bool}}: // Some known to be non-descriptors
                                    case @{{int}}:
                                    case @{{long}}:
                                    case @{{str}}:
                                        break;
                                    default:
                                        // check for __get__ method in ga
                                        if (ga['$inst'] === true) {
                                            var get$ = @{{_getattr}}(ga, '__get__');
                                            if (typeof get$ != 'undefined') {
                                                ga = @{{fcall}}(this, null, get$, ga, cls, cls['__class__']);
                                            }
                                        }
                                        break;
                                }
                            }
                            @{{noraise}} = @{{AttributeError}};
                            method$ = @{{fcall}}(this, null, ga, _mro$, '__init__');
                            @{{noraise}} = _noraise$;
                            if (method$ === @{{AttributeError}}) {
                                method$ = [][1];
                            }
                            // TODO : unbind method$ ?
                            break;
                        }
                    }
                }
                break;
            default:
                method$ = cls['__init__'];
                if (typeof method$ == "undefined" && typeof cls['$dict'] != "undefined") {
                    method$ = cls['$dict']['__init__'];
                }
        }
        if (method$ !== B$__init__) {
            if (_meth_src['$inst'] === false && instance['__class__'] !== @{{module}} && typeof method$ != "undefined" && typeof method$['$inst'] != "undefined") {
                switch (method$['__class__']) {
                    case @{{function}}:
                        var _new_dst$ = function ( ) {
                            var args = Array.prototype.slice.call(arguments);
                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                if (arguments.callee['im_self'] !== null) {
                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                }
                            }
                            var a = @{{_getattr}}(arguments.callee, '__call__');
                            if (typeof a == "undefined") {
                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                            }
                            if (args.length >= 3) {
                                var len = args.length;
                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                            }
                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                        _new_dst$['toString'] = function ( ) {
                            try {
                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                            } catch (e) {
                            }
                            try {
                                return "<" + this.__class__.__name__ + " instance>";
                            } catch (e) {
                            }
                            return "<instance>";
                        };
                        _new_dst$['$inst'] = true;
                        if (typeof @{{instancemethod}} == "undefined") {
                            debugger;
                        }
                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                            _new_dst$['__dict__'] = B$dict();
                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                        }
                        _new_dst$['__class__'] = @{{instancemethod}};
                        _new_dst$['im_class'] = instance['$inst'] === true ? instance['__class__'] : instance;
                        _new_dst$['im_func'] = method$;
                        _new_dst$['im_self'] = instance['$inst'] === true ? instance : null;
                        method$ = _new_dst$;
                        break;
                    case @{{staticmethod}}:
                        method$ = method$['im_func'];
                        break;
                    case @{{classmethod}}:
                        var _new_dst$ = function ( ) {
                            var args = Array.prototype.slice.call(arguments);
                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                if (arguments.callee['im_self'] !== null) {
                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                }
                            }
                            var a = @{{_getattr}}(arguments.callee, '__call__');
                            if (typeof a == "undefined") {
                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                            }
                            if (args.length >= 3) {
                                var len = args.length;
                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                            }
                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                        _new_dst$['toString'] = function ( ) {
                            try {
                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                            } catch (e) {
                            }
                            try {
                                return "<" + this.__class__.__name__ + " instance>";
                            } catch (e) {
                            }
                            return "<instance>";
                        };
                        _new_dst$['$inst'] = true;
                        if (typeof @{{instancemethod}} == "undefined") {
                            debugger;
                        }
                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                            _new_dst$['__dict__'] = B$dict();
                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                        }
                        _new_dst$['__class__'] = @{{instancemethod}};
                        _new_dst$['im_class'] = instance['$inst'] === true ? instance['__class__'] : instance;
                        _new_dst$['im_func'] = method$['im_func'];
                        _new_dst$['im_self'] = instance['$inst'] === true ? instance['__class__'] : instance;
                        method$ = _new_dst$;
                        break;
                    case @{{bool}}: // Some known to be non-descriptors
                    case @{{int}}:
                    case @{{long}}:
                    case @{{str}}:
                        break;
                    default:
                        // check for __get__ method in method$
                        if (method$['$inst'] === true) {
                            var get$ = @{{_getattr}}(method$, '__get__');
                            if (typeof get$ != 'undefined') {
                                method$ = @{{fcall}}(this, null, get$, method$, instance, instance['__class__']);
                            }
                        }
                        break;
                }
            }
            var ret = @{{fcall}}.apply(module, [module, null, method$, null].concat(args));
            if (ret !== @{{None}} && ret !== null) {
                if (ret['__class__'] != "undefined") {
                    return @{{raise}}($new(@{{TypeError}}, B$str("__init__() should return None, not '" + ret['__class__']['__name__'] + "'")));
                }
                return @{{raise}}($new(@{{TypeError}}, B$str("__init__() should return None")));
            }
        }
    }
    return instance;
}

//var $newext = @{{$newext}} = function ($cls/*, args, star_args, dstar_args, named_args*/) {
// function ($cls/*, args, star_args, dstar_args, named_args*/)
var $newext = @{{$newext}} = func(m$, null, {}, '__call__', 0, ['cls'], null, null, null, function ($cls) {
    var args, cls = $cls;
    if (arguments.length >= 4) {
        args = Array.prototype.slice.call(arguments, 1);
    } else {
        args = Array.prototype.slice.call(arguments, 0);
        cls = args[0].__array[0];
        args[0].__array.shift();
    }
    var method$, instance, mro$, module = this['__class__'] === @{{module}} ? this : null;
    method$ = [][1];
    var mro$ = cls['__mro__'];
    var _meth_src = cls;
    switch (cls['$inst']) {
        case true:
            if (cls['__class__'] === @{{module}}) {
                method$ = cls['$dict']['__new__'];
                break;
            } else if (cls['__class__'] === @{{function}}) {
                switch ('__new__'.charAt(0)) {
                    case 'i':
                    case '_':
                        method$ = cls['__new__'];
                }
                break;
            }
            var _noraise$ = @{{noraise}};
            var ga;
            mro$ = cls['__class__']['__mro__'];
            for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                var _mro$ = mro$[mro_i$];
                var ga = _mro$['__getattribute__'];
                if (typeof ga == "undefined") {
                    if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                        continue;
                    }
                    ga = _mro$['$dict']['__getattribute__'];
                }
                if (cls['__class__']['$inst'] === false && cls['__class__'] !== @{{module}} && typeof cls != "undefined" && typeof cls['$inst'] != "undefined") {
                    switch (ga['__class__']) {
                        case @{{function}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                            _new_dst$['im_func'] = ga;
                            _new_dst$['im_self'] = cls['$inst'] === true ? cls : null;
                            ga = _new_dst$;
                            break;
                        case @{{staticmethod}}:
                            ga = ga['im_func'];
                            break;
                        case @{{classmethod}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                            _new_dst$['im_func'] = ga['im_func'];
                            _new_dst$['im_self'] = cls['$inst'] === true ? cls['__class__'] : cls;
                            ga = _new_dst$;
                            break;
                        case @{{bool}}: // Some known to be non-descriptors
                        case @{{int}}:
                        case @{{long}}:
                        case @{{str}}:
                            break;
                        default:
                            // check for __get__ method in ga
                            if (ga['$inst'] === true) {
                                var get$ = @{{_getattr}}(ga, '__get__');
                                if (typeof get$ != 'undefined') {
                                    ga = @{{fcall}}(this, null, get$, ga, cls, cls['__class__']);
                                }
                            }
                            break;
                    }
                }
                @{{noraise}} = @{{AttributeError}};
                method$ = @{{fcall}}(this, null, ga, _mro$, '__new__');
                @{{noraise}} = _noraise$;
                if (method$ === @{{AttributeError}}) {
                    method$ = [][1];
                }
                _meth_src = cls['__class__'];
                cls = cls['__class__'];
                break;
            }
            if (typeof method$ == "undefined") {
                if (typeof cls['$dict'] != "undefined") {
                    method$ = cls['$dict']['__new__'];
                    if (typeof method$ != "undefined") {
                        if (method$ !== {}['__new__']) {
                            break;
                        }
                        method$ = [][1];
                    }
                }
                switch ('__new__'.charAt(0)) {
                    case 'i':
                    case '_':
                        method$ = cls['__new__'];
                }
                if (typeof method$ != "undefined") {
                    break;
                }
            }
        case false:
            if (typeof method$ == "undefined") {
                var _mro$, ga;
                if (cls['$inst'] === true) {
                    _meth_src = cls['__class__'];
                } else {
                    switch ('__new__'.charAt(0)) {
                        case 'i':
                        case '_':
                            method$ = cls['__new__'];
                    }
                    if (typeof method$ != "undefined") {
                        break;
                    }

                }
                if (typeof method$ == "undefined") {
                    for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        method$ = _mro$['$dict']['__new__'];
                        if (typeof method$ != "undefined") {
                            if (method$ !== {}['__new__']) {
                                break;
                            }
                            method$ = [][1];
                        }
                        switch ('__new__'.charAt(0)) {
                            case 'i':
                            case '_':
                                method$ = _mro$['__new__'];
                        }
                        if (typeof method$ != "undefined") {
                            break;
                        }
                    }
                }
                if (typeof method$ == "undefined" && '__new__' !== '__get__') {
                    for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattr__'];
                        if (cls['__class__']['$inst'] === false && cls['__class__'] !== @{{module}} && typeof cls != "undefined" && typeof cls['$inst'] != "undefined") {
                            switch (ga['__class__']) {
                                case @{{function}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                    _new_dst$['im_func'] = ga;
                                    _new_dst$['im_self'] = cls['$inst'] === true ? cls : null;
                                    ga = _new_dst$;
                                    break;
                                case @{{staticmethod}}:
                                    ga = ga['im_func'];
                                    break;
                                case @{{classmethod}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                    _new_dst$['im_func'] = ga['im_func'];
                                    _new_dst$['im_self'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                    ga = _new_dst$;
                                    break;
                                case @{{bool}}: // Some known to be non-descriptors
                                case @{{int}}:
                                case @{{long}}:
                                case @{{str}}:
                                    break;
                                default:
                                    // check for __get__ method in ga
                                    if (ga['$inst'] === true) {
                                        var get$ = @{{_getattr}}(ga, '__get__');
                                        if (typeof get$ != 'undefined') {
                                            ga = @{{fcall}}(this, null, get$, ga, cls, cls['__class__']);
                                        }
                                    }
                                    break;
                            }
                        }
                        @{{noraise}} = @{{AttributeError}};
                        method$ = @{{fcall}}(this, null, ga, _mro$, '__new__');
                        @{{noraise}} = _noraise$;
                        if (method$ === @{{AttributeError}}) {
                            method$ = [][1];
                        }
                        // TODO : unbind method$ ?
                        break;
                    }
                }
            }
            break;
        default:
            method$ = cls['__new__'];
            if (typeof method$ == "undefined" && typeof cls['$dict'] != "undefined") {
                method$ = cls['$dict']['__new__'];
            }
    }
    if (method$ === B$__new__) {
        var instance = function ( ) {
            var args = Array.prototype.slice.call(arguments);
            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                if (arguments.callee['im_self'] !== null) {
                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                }
            }
            var a = @{{_getattr}}(arguments.callee, '__call__');
            if (typeof a == "undefined") {
                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
            }
            if (args.length >= 3) {
                var len = args.length;
                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                }
            }
            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
        }
        instance['toString'] = function ( ) {
            try {
                return @{{mcall}}(this, null, this, '__str__').valueOf();
            } catch (e) {
            }
            try {
                return "<" + this.__class__.__name__ + " instance>";
            } catch (e) {
            }
            return "<instance>";
        };
        instance['$inst'] = true;
        if (typeof cls == "undefined") {
            debugger;
        }
        if (typeof cls['__slots__'] == "undefined" || cls['__slots__'].length > 0) {
            instance['__dict__'] = B$dict();
            instance['$dict'] = instance['__dict__']['__object'];
        }
        instance['__class__'] = cls;
    } else {
        instance = @{{fcallext}}.apply(module, [module, null, method$, cls, cls].concat(args));
    }
    if (instance['$inst'] === true) {
        method$ = [][1];
        var mro$ = cls['__mro__'];
        var _meth_src = cls;
        switch (cls['$inst']) {
            case true:
                if (cls['__class__'] === @{{module}}) {
                    method$ = cls['$dict']['__init__'];
                    break;
                } else if (cls['__class__'] === @{{function}}) {
                    switch ('__init__'.charAt(0)) {
                        case 'i':
                        case '_':
                            method$ = cls['__init__'];
                    }
                    break;
                }
                var _noraise$ = @{{noraise}};
                var ga;
                mro$ = cls['__class__']['__mro__'];
                for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                    var _mro$ = mro$[mro_i$];
                    var ga = _mro$['__getattribute__'];
                    if (typeof ga == "undefined") {
                        if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattribute__'];
                    }
                    if (cls['__class__']['$inst'] === false && cls['__class__'] !== @{{module}} && typeof cls != "undefined" && typeof cls['$inst'] != "undefined") {
                        switch (ga['__class__']) {
                            case @{{function}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                _new_dst$['im_func'] = ga;
                                _new_dst$['im_self'] = cls['$inst'] === true ? cls : null;
                                ga = _new_dst$;
                                break;
                            case @{{staticmethod}}:
                                ga = ga['im_func'];
                                break;
                            case @{{classmethod}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                _new_dst$['im_func'] = ga['im_func'];
                                _new_dst$['im_self'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                ga = _new_dst$;
                                break;
                            case @{{bool}}: // Some known to be non-descriptors
                            case @{{int}}:
                            case @{{long}}:
                            case @{{str}}:
                                break;
                            default:
                                // check for __get__ method in ga
                                if (ga['$inst'] === true) {
                                    var get$ = @{{_getattr}}(ga, '__get__');
                                    if (typeof get$ != 'undefined') {
                                        ga = @{{fcall}}(this, null, get$, ga, cls, cls['__class__']);
                                    }
                                }
                                break;
                        }
                    }
                    @{{noraise}} = @{{AttributeError}};
                    method$ = @{{fcall}}(this, null, ga, _mro$, '__init__');
                    @{{noraise}} = _noraise$;
                    if (method$ === @{{AttributeError}}) {
                        method$ = [][1];
                    }
                    _meth_src = cls['__class__'];
                    cls = cls['__class__'];
                    break;
                }
                if (typeof method$ == "undefined") {
                    if (typeof cls['$dict'] != "undefined") {
                        method$ = cls['$dict']['__init__'];
                        if (typeof method$ != "undefined") {
                            if (method$ !== {}['__init__']) {
                                break;
                            }
                            method$ = [][1];
                        }
                    }
                    switch ('__init__'.charAt(0)) {
                        case 'i':
                        case '_':
                            method$ = cls['__init__'];
                    }
                    if (typeof method$ != "undefined") {
                        break;
                    }
                }
            case false:
                if (typeof method$ == "undefined") {
                    var _mro$, ga;
                    if (cls['$inst'] === true) {
                        _meth_src = cls['__class__'];
                    } else {
                        switch ('__init__'.charAt(0)) {
                            case 'i':
                            case '_':
                                method$ = cls['__init__'];
                        }
                        if (typeof method$ != "undefined") {
                            break;
                        }

                    }
                    if (typeof method$ == "undefined") {
                        for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            method$ = _mro$['$dict']['__init__'];
                            if (typeof method$ != "undefined") {
                                if (method$ !== {}['__init__']) {
                                    break;
                                }
                                method$ = [][1];
                            }
                            switch ('__init__'.charAt(0)) {
                                case 'i':
                                case '_':
                                    method$ = _mro$['__init__'];
                            }
                            if (typeof method$ != "undefined") {
                                break;
                            }
                        }
                    }
                    if (typeof method$ == "undefined" && '__init__' !== '__get__') {
                        for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                continue;
                            }
                            ga = _mro$['$dict']['__getattr__'];
                            if (cls['__class__']['$inst'] === false && cls['__class__'] !== @{{module}} && typeof cls != "undefined" && typeof cls['$inst'] != "undefined") {
                                switch (ga['__class__']) {
                                    case @{{function}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                        _new_dst$['im_func'] = ga;
                                        _new_dst$['im_self'] = cls['$inst'] === true ? cls : null;
                                        ga = _new_dst$;
                                        break;
                                    case @{{staticmethod}}:
                                        ga = ga['im_func'];
                                        break;
                                    case @{{classmethod}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                        _new_dst$['im_func'] = ga['im_func'];
                                        _new_dst$['im_self'] = cls['$inst'] === true ? cls['__class__'] : cls;
                                        ga = _new_dst$;
                                        break;
                                    case @{{bool}}: // Some known to be non-descriptors
                                    case @{{int}}:
                                    case @{{long}}:
                                    case @{{str}}:
                                        break;
                                    default:
                                        // check for __get__ method in ga
                                        if (ga['$inst'] === true) {
                                            var get$ = @{{_getattr}}(ga, '__get__');
                                            if (typeof get$ != 'undefined') {
                                                ga = @{{fcall}}(this, null, get$, ga, cls, cls['__class__']);
                                            }
                                        }
                                        break;
                                }
                            }
                            @{{noraise}} = @{{AttributeError}};
                            method$ = @{{fcall}}(this, null, ga, _mro$, '__init__');
                            @{{noraise}} = _noraise$;
                            if (method$ === @{{AttributeError}}) {
                                method$ = [][1];
                            }
                            // TODO : unbind method$ ?
                            break;
                        }
                    }
                }
                break;
            default:
                method$ = cls['__init__'];
                if (typeof method$ == "undefined" && typeof cls['$dict'] != "undefined") {
                    method$ = cls['$dict']['__init__'];
                }
        }
        if (method$ !== B$__init__) {
            if (_meth_src['$inst'] === false && instance['__class__'] !== @{{module}} && typeof method$ != "undefined" && typeof method$['$inst'] != "undefined") {
                switch (method$['__class__']) {
                    case @{{function}}:
                        var _new_dst$ = function ( ) {
                            var args = Array.prototype.slice.call(arguments);
                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                if (arguments.callee['im_self'] !== null) {
                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                }
                            }
                            var a = @{{_getattr}}(arguments.callee, '__call__');
                            if (typeof a == "undefined") {
                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                            }
                            if (args.length >= 3) {
                                var len = args.length;
                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                            }
                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                        _new_dst$['toString'] = function ( ) {
                            try {
                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                            } catch (e) {
                            }
                            try {
                                return "<" + this.__class__.__name__ + " instance>";
                            } catch (e) {
                            }
                            return "<instance>";
                        };
                        _new_dst$['$inst'] = true;
                        if (typeof @{{instancemethod}} == "undefined") {
                            debugger;
                        }
                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                            _new_dst$['__dict__'] = B$dict();
                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                        }
                        _new_dst$['__class__'] = @{{instancemethod}};
                        _new_dst$['im_class'] = instance['$inst'] === true ? instance['__class__'] : instance;
                        _new_dst$['im_func'] = method$;
                        _new_dst$['im_self'] = instance['$inst'] === true ? instance : null;
                        method$ = _new_dst$;
                        break;
                    case @{{staticmethod}}:
                        method$ = method$['im_func'];
                        break;
                    case @{{classmethod}}:
                        var _new_dst$ = function ( ) {
                            var args = Array.prototype.slice.call(arguments);
                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                if (arguments.callee['im_self'] !== null) {
                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                }
                            }
                            var a = @{{_getattr}}(arguments.callee, '__call__');
                            if (typeof a == "undefined") {
                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                            }
                            if (args.length >= 3) {
                                var len = args.length;
                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                            }
                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                        _new_dst$['toString'] = function ( ) {
                            try {
                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                            } catch (e) {
                            }
                            try {
                                return "<" + this.__class__.__name__ + " instance>";
                            } catch (e) {
                            }
                            return "<instance>";
                        };
                        _new_dst$['$inst'] = true;
                        if (typeof @{{instancemethod}} == "undefined") {
                            debugger;
                        }
                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                            _new_dst$['__dict__'] = B$dict();
                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                        }
                        _new_dst$['__class__'] = @{{instancemethod}};
                        _new_dst$['im_class'] = instance['$inst'] === true ? instance['__class__'] : instance;
                        _new_dst$['im_func'] = method$['im_func'];
                        _new_dst$['im_self'] = instance['$inst'] === true ? instance['__class__'] : instance;
                        method$ = _new_dst$;
                        break;
                    case @{{bool}}: // Some known to be non-descriptors
                    case @{{int}}:
                    case @{{long}}:
                    case @{{str}}:
                        break;
                    default:
                        // check for __get__ method in method$
                        if (method$['$inst'] === true) {
                            var get$ = @{{_getattr}}(method$, '__get__');
                            if (typeof get$ != 'undefined') {
                                method$ = @{{fcall}}(this, null, get$, method$, instance, instance['__class__']);
                            }
                        }
                        break;
                }
            }
            var ret = @{{fcallext}}.apply(module, [module, null, method$, null].concat(args));
            if (ret !== @{{None}} && ret !== null) {
                if (ret['__class__'] != "undefined") {
                    return @{{raise}}($new(@{{TypeError}}, B$str("__init__() should return None, not '" + ret['__class__']['__name__'] + "'")));
                }
                return @{{raise}}($new(@{{TypeError}}, B$str("__init__() should return None")));
            }
        }
    }
    return instance;
});

// Some short-cut functions for specific instances
function B$bool($v) {

    var v = $v.valueOf();
    switch (v) {
        case null:
        case false:
        case 0:
        case '':
            return @{{False}};
        case true:
        case 1:
            return @{{True}};
    }
    if (typeof v == 'number' || typeof v == 'string') {
        return @{{True}};
    }
    if ($v['$inst'] === true) {
        var mro$, attr, attrs = ['__nonzero__', '__len__'];
        for (var i = 0; i < attrs.length; i++) {
            attr = attrs[i];
            v = [][1];
            var mro$ = $v['__mro__'];
            var _meth_src = $v;
            switch ($v['$inst']) {
                case true:
                    if ($v['__class__'] === @{{module}}) {
                        v = $v['$dict'][attr];
                        break;
                    } else if ($v['__class__'] === @{{function}}) {
                        switch (attr.charAt(0)) {
                            case 'i':
                            case '_':
                                v = $v[attr];
                        }
                        break;
                    }
                    var _noraise$ = @{{noraise}};
                    var ga;
                    mro$ = $v['__class__']['__mro__'];
                    for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                        var _mro$ = mro$[mro_i$];
                        var ga = _mro$['__getattribute__'];
                        if (typeof ga == "undefined") {
                            if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                                continue;
                            }
                            ga = _mro$['$dict']['__getattribute__'];
                        }
                        if ($v['__class__']['$inst'] === false && $v['__class__'] !== @{{module}} && typeof $v != "undefined" && typeof $v['$inst'] != "undefined") {
                            switch (ga['__class__']) {
                                case @{{function}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                    _new_dst$['im_func'] = ga;
                                    _new_dst$['im_self'] = $v['$inst'] === true ? $v : null;
                                    ga = _new_dst$;
                                    break;
                                case @{{staticmethod}}:
                                    ga = ga['im_func'];
                                    break;
                                case @{{classmethod}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                    _new_dst$['im_func'] = ga['im_func'];
                                    _new_dst$['im_self'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                    ga = _new_dst$;
                                    break;
                                case @{{bool}}: // Some known to be non-descriptors
                                case @{{int}}:
                                case @{{long}}:
                                case @{{str}}:
                                    break;
                                default:
                                    // check for __get__ method in ga
                                    if (ga['$inst'] === true) {
                                        var get$ = @{{_getattr}}(ga, '__get__');
                                        if (typeof get$ != 'undefined') {
                                            ga = @{{fcall}}(this, null, get$, ga, $v, $v['__class__']);
                                        }
                                    }
                                    break;
                            }
                        }
                        @{{noraise}} = @{{AttributeError}};
                        v = @{{fcall}}(this, null, ga, _mro$, attr);
                        @{{noraise}} = _noraise$;
                        if (v === @{{AttributeError}}) {
                            v = [][1];
                        }
                        _meth_src = $v['__class__'];
                        $v = $v['__class__'];
                        break;
                    }
                    if (typeof v == "undefined") {
                        if (typeof $v['$dict'] != "undefined") {
                            v = $v['$dict'][attr];
                            if (typeof v != "undefined") {
                                if (v !== {}[attr]) {
                                    break;
                                }
                                v = [][1];
                            }
                        }
                        switch (attr.charAt(0)) {
                            case 'i':
                            case '_':
                                v = $v[attr];
                        }
                        if (typeof v != "undefined") {
                            break;
                        }
                    }
                case false:
                    if (typeof v == "undefined") {
                        var _mro$, ga;
                        if ($v['$inst'] === true) {
                            _meth_src = $v['__class__'];
                        } else {
                            switch (attr.charAt(0)) {
                                case 'i':
                                case '_':
                                    v = $v[attr];
                            }
                            if (typeof v != "undefined") {
                                break;
                            }

                        }
                        if (typeof v == "undefined") {
                            for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                                _mro$ = mro$[mro_i$];
                                v = _mro$['$dict'][attr];
                                if (typeof v != "undefined") {
                                    if (v !== {}[attr]) {
                                        break;
                                    }
                                    v = [][1];
                                }
                                switch (attr.charAt(0)) {
                                    case 'i':
                                    case '_':
                                        v = _mro$[attr];
                                }
                                if (typeof v != "undefined") {
                                    break;
                                }
                            }
                        }
                        if (typeof v == "undefined" && attr !== '__get__') {
                            for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                                _mro$ = mro$[mro_i$];
                                if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                    continue;
                                }
                                ga = _mro$['$dict']['__getattr__'];
                                if ($v['__class__']['$inst'] === false && $v['__class__'] !== @{{module}} && typeof $v != "undefined" && typeof $v['$inst'] != "undefined") {
                                    switch (ga['__class__']) {
                                        case @{{function}}:
                                            var _new_dst$ = function ( ) {
                                                var args = Array.prototype.slice.call(arguments);
                                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                    if (arguments.callee['im_self'] !== null) {
                                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                    }
                                                }
                                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                                if (typeof a == "undefined") {
                                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                }
                                                if (args.length >= 3) {
                                                    var len = args.length;
                                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                    }
                                                }
                                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                            _new_dst$['toString'] = function ( ) {
                                                try {
                                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                } catch (e) {
                                                }
                                                try {
                                                    return "<" + this.__class__.__name__ + " instance>";
                                                } catch (e) {
                                                }
                                                return "<instance>";
                                            };
                                            _new_dst$['$inst'] = true;
                                            if (typeof @{{instancemethod}} == "undefined") {
                                                debugger;
                                            }
                                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                _new_dst$['__dict__'] = B$dict();
                                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                            }
                                            _new_dst$['__class__'] = @{{instancemethod}};
                                            _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                            _new_dst$['im_func'] = ga;
                                            _new_dst$['im_self'] = $v['$inst'] === true ? $v : null;
                                            ga = _new_dst$;
                                            break;
                                        case @{{staticmethod}}:
                                            ga = ga['im_func'];
                                            break;
                                        case @{{classmethod}}:
                                            var _new_dst$ = function ( ) {
                                                var args = Array.prototype.slice.call(arguments);
                                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                    if (arguments.callee['im_self'] !== null) {
                                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                    }
                                                }
                                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                                if (typeof a == "undefined") {
                                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                }
                                                if (args.length >= 3) {
                                                    var len = args.length;
                                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                    }
                                                }
                                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                            _new_dst$['toString'] = function ( ) {
                                                try {
                                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                } catch (e) {
                                                }
                                                try {
                                                    return "<" + this.__class__.__name__ + " instance>";
                                                } catch (e) {
                                                }
                                                return "<instance>";
                                            };
                                            _new_dst$['$inst'] = true;
                                            if (typeof @{{instancemethod}} == "undefined") {
                                                debugger;
                                            }
                                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                _new_dst$['__dict__'] = B$dict();
                                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                            }
                                            _new_dst$['__class__'] = @{{instancemethod}};
                                            _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                            _new_dst$['im_func'] = ga['im_func'];
                                            _new_dst$['im_self'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                            ga = _new_dst$;
                                            break;
                                        case @{{bool}}: // Some known to be non-descriptors
                                        case @{{int}}:
                                        case @{{long}}:
                                        case @{{str}}:
                                            break;
                                        default:
                                            // check for __get__ method in ga
                                            if (ga['$inst'] === true) {
                                                var get$ = @{{_getattr}}(ga, '__get__');
                                                if (typeof get$ != 'undefined') {
                                                    ga = @{{fcall}}(this, null, get$, ga, $v, $v['__class__']);
                                                }
                                            }
                                            break;
                                    }
                                }
                                @{{noraise}} = @{{AttributeError}};
                                v = @{{fcall}}(this, null, ga, _mro$, attr);
                                @{{noraise}} = _noraise$;
                                if (v === @{{AttributeError}}) {
                                    v = [][1];
                                }
                                // TODO : unbind v ?
                                break;
                            }
                        }
                    }
                    break;
                default:
                    v = $v[attr];
                    if (typeof v == "undefined" && typeof $v['$dict'] != "undefined") {
                        v = $v['$dict'][attr];
                    }
            }
            if (typeof v != "undefined") {
                if (_meth_src['$inst'] === false && $v['__class__'] !== @{{module}} && typeof v != "undefined" && typeof v['$inst'] != "undefined") {
                    switch (v['__class__']) {
                        case @{{function}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                            _new_dst$['im_func'] = v;
                            _new_dst$['im_self'] = $v['$inst'] === true ? $v : null;
                            v = _new_dst$;
                            break;
                        case @{{staticmethod}}:
                            v = v['im_func'];
                            break;
                        case @{{classmethod}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                            _new_dst$['im_func'] = v['im_func'];
                            _new_dst$['im_self'] = $v['$inst'] === true ? $v['__class__'] : $v;
                            v = _new_dst$;
                            break;
                        case @{{bool}}: // Some known to be non-descriptors
                        case @{{int}}:
                        case @{{long}}:
                        case @{{str}}:
                            break;
                        default:
                            // check for __get__ method in v
                            if (v['$inst'] === true) {
                                var get$ = @{{_getattr}}(v, '__get__');
                                if (typeof get$ != 'undefined') {
                                    v = @{{fcall}}(this, null, get$, v, $v, $v['__class__']);
                                }
                            }
                            break;
                    }
                }
                v = @{{fcall}}(this, null, v, $v);
                switch (attr) {
                    case '__nonzero__':
                        return v.__v ? @{{True}} : @{{False}};
                    case '__len__':
                        return v.__v != 0 ? @{{True}} : @{{False}};
                }
            }
        }
    }
    return @{{True}};
};
b$ = @{{B$bool}} = B$bool;

function B$booljs($v) {
    if ($v === null) return false;

    var v = $v.valueOf();
    switch (v) {
        case null:
        case false:
        case 0:
        case '':
            return false;
        case true:
        case 1:
            return true;
    }
    if (typeof v == 'number' || typeof v == 'string') {
        return true;
    }
    if ($v['$inst'] === true) {
        var mro$, attr, attrs = ['__nonzero__', '__len__'];
        for (var i = 0; i < attrs.length; i++) {
            attr = attrs[i];
            v = [][1];
            var mro$ = $v['__mro__'];
            var _meth_src = $v;
            switch ($v['$inst']) {
                case true:
                    if ($v['__class__'] === @{{module}}) {
                        v = $v['$dict'][attr];
                        break;
                    } else if ($v['__class__'] === @{{function}}) {
                        switch (attr.charAt(0)) {
                            case 'i':
                            case '_':
                                v = $v[attr];
                        }
                        break;
                    }
                    var _noraise$ = @{{noraise}};
                    var ga;
                    mro$ = $v['__class__']['__mro__'];
                    for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                        var _mro$ = mro$[mro_i$];
                        var ga = _mro$['__getattribute__'];
                        if (typeof ga == "undefined") {
                            if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                                continue;
                            }
                            ga = _mro$['$dict']['__getattribute__'];
                        }
                        if ($v['__class__']['$inst'] === false && $v['__class__'] !== @{{module}} && typeof $v != "undefined" && typeof $v['$inst'] != "undefined") {
                            switch (ga['__class__']) {
                                case @{{function}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                    _new_dst$['im_func'] = ga;
                                    _new_dst$['im_self'] = $v['$inst'] === true ? $v : null;
                                    ga = _new_dst$;
                                    break;
                                case @{{staticmethod}}:
                                    ga = ga['im_func'];
                                    break;
                                case @{{classmethod}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                    _new_dst$['im_func'] = ga['im_func'];
                                    _new_dst$['im_self'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                    ga = _new_dst$;
                                    break;
                                case @{{bool}}: // Some known to be non-descriptors
                                case @{{int}}:
                                case @{{long}}:
                                case @{{str}}:
                                    break;
                                default:
                                    // check for __get__ method in ga
                                    if (ga['$inst'] === true) {
                                        var get$ = @{{_getattr}}(ga, '__get__');
                                        if (typeof get$ != 'undefined') {
                                            ga = @{{fcall}}(this, null, get$, ga, $v, $v['__class__']);
                                        }
                                    }
                                    break;
                            }
                        }
                        @{{noraise}} = @{{AttributeError}};
                        v = @{{fcall}}(this, null, ga, _mro$, attr);
                        @{{noraise}} = _noraise$;
                        if (v === @{{AttributeError}}) {
                            v = [][1];
                        }
                        _meth_src = $v['__class__'];
                        $v = $v['__class__'];
                        break;
                    }
                    if (typeof v == "undefined") {
                        if (typeof $v['$dict'] != "undefined") {
                            v = $v['$dict'][attr];
                            if (typeof v != "undefined") {
                                if (v !== {}[attr]) {
                                    break;
                                }
                                v = [][1];
                            }
                        }
                        switch (attr.charAt(0)) {
                            case 'i':
                            case '_':
                                v = $v[attr];
                        }
                        if (typeof v != "undefined") {
                            break;
                        }
                    }
                case false:
                    if (typeof v == "undefined") {
                        var _mro$, ga;
                        if ($v['$inst'] === true) {
                            _meth_src = $v['__class__'];
                        } else {
                            switch (attr.charAt(0)) {
                                case 'i':
                                case '_':
                                    v = $v[attr];
                            }
                            if (typeof v != "undefined") {
                                break;
                            }

                        }
                        if (typeof v == "undefined") {
                            for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                                _mro$ = mro$[mro_i$];
                                v = _mro$['$dict'][attr];
                                if (typeof v != "undefined") {
                                    if (v !== {}[attr]) {
                                        break;
                                    }
                                    v = [][1];
                                }
                                switch (attr.charAt(0)) {
                                    case 'i':
                                    case '_':
                                        v = _mro$[attr];
                                }
                                if (typeof v != "undefined") {
                                    break;
                                }
                            }
                        }
                        if (typeof v == "undefined" && attr !== '__get__') {
                            for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                                _mro$ = mro$[mro_i$];
                                if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                    continue;
                                }
                                ga = _mro$['$dict']['__getattr__'];
                                if ($v['__class__']['$inst'] === false && $v['__class__'] !== @{{module}} && typeof $v != "undefined" && typeof $v['$inst'] != "undefined") {
                                    switch (ga['__class__']) {
                                        case @{{function}}:
                                            var _new_dst$ = function ( ) {
                                                var args = Array.prototype.slice.call(arguments);
                                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                    if (arguments.callee['im_self'] !== null) {
                                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                    }
                                                }
                                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                                if (typeof a == "undefined") {
                                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                }
                                                if (args.length >= 3) {
                                                    var len = args.length;
                                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                    }
                                                }
                                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                            _new_dst$['toString'] = function ( ) {
                                                try {
                                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                } catch (e) {
                                                }
                                                try {
                                                    return "<" + this.__class__.__name__ + " instance>";
                                                } catch (e) {
                                                }
                                                return "<instance>";
                                            };
                                            _new_dst$['$inst'] = true;
                                            if (typeof @{{instancemethod}} == "undefined") {
                                                debugger;
                                            }
                                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                _new_dst$['__dict__'] = B$dict();
                                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                            }
                                            _new_dst$['__class__'] = @{{instancemethod}};
                                            _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                            _new_dst$['im_func'] = ga;
                                            _new_dst$['im_self'] = $v['$inst'] === true ? $v : null;
                                            ga = _new_dst$;
                                            break;
                                        case @{{staticmethod}}:
                                            ga = ga['im_func'];
                                            break;
                                        case @{{classmethod}}:
                                            var _new_dst$ = function ( ) {
                                                var args = Array.prototype.slice.call(arguments);
                                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                    if (arguments.callee['im_self'] !== null) {
                                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                    }
                                                }
                                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                                if (typeof a == "undefined") {
                                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                }
                                                if (args.length >= 3) {
                                                    var len = args.length;
                                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                    }
                                                }
                                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                            _new_dst$['toString'] = function ( ) {
                                                try {
                                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                } catch (e) {
                                                }
                                                try {
                                                    return "<" + this.__class__.__name__ + " instance>";
                                                } catch (e) {
                                                }
                                                return "<instance>";
                                            };
                                            _new_dst$['$inst'] = true;
                                            if (typeof @{{instancemethod}} == "undefined") {
                                                debugger;
                                            }
                                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                _new_dst$['__dict__'] = B$dict();
                                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                            }
                                            _new_dst$['__class__'] = @{{instancemethod}};
                                            _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                            _new_dst$['im_func'] = ga['im_func'];
                                            _new_dst$['im_self'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                            ga = _new_dst$;
                                            break;
                                        case @{{bool}}: // Some known to be non-descriptors
                                        case @{{int}}:
                                        case @{{long}}:
                                        case @{{str}}:
                                            break;
                                        default:
                                            // check for __get__ method in ga
                                            if (ga['$inst'] === true) {
                                                var get$ = @{{_getattr}}(ga, '__get__');
                                                if (typeof get$ != 'undefined') {
                                                    ga = @{{fcall}}(this, null, get$, ga, $v, $v['__class__']);
                                                }
                                            }
                                            break;
                                    }
                                }
                                @{{noraise}} = @{{AttributeError}};
                                v = @{{fcall}}(this, null, ga, _mro$, attr);
                                @{{noraise}} = _noraise$;
                                if (v === @{{AttributeError}}) {
                                    v = [][1];
                                }
                                // TODO : unbind v ?
                                break;
                            }
                        }
                    }
                    break;
                default:
                    v = $v[attr];
                    if (typeof v == "undefined" && typeof $v['$dict'] != "undefined") {
                        v = $v['$dict'][attr];
                    }
            }
            if (typeof v != "undefined") {
                if (_meth_src['$inst'] === false && $v['__class__'] !== @{{module}} && typeof v != "undefined" && typeof v['$inst'] != "undefined") {
                    switch (v['__class__']) {
                        case @{{function}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                            _new_dst$['im_func'] = v;
                            _new_dst$['im_self'] = $v['$inst'] === true ? $v : null;
                            v = _new_dst$;
                            break;
                        case @{{staticmethod}}:
                            v = v['im_func'];
                            break;
                        case @{{classmethod}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                            _new_dst$['im_func'] = v['im_func'];
                            _new_dst$['im_self'] = $v['$inst'] === true ? $v['__class__'] : $v;
                            v = _new_dst$;
                            break;
                        case @{{bool}}: // Some known to be non-descriptors
                        case @{{int}}:
                        case @{{long}}:
                        case @{{str}}:
                            break;
                        default:
                            // check for __get__ method in v
                            if (v['$inst'] === true) {
                                var get$ = @{{_getattr}}(v, '__get__');
                                if (typeof get$ != 'undefined') {
                                    v = @{{fcall}}(this, null, get$, v, $v, $v['__class__']);
                                }
                            }
                            break;
                    }
                }
                v = @{{fcall}}(this, null, v, $v);
                switch (attr) {
                    case '__nonzero__':
                        return v.__v ? true : false;
                    case '__len__':
                        return v.__v != 0 ? true : false;
                }
            }
        }
    }
    return true;
};
_b = @{{B$booljs}} = B$booljs;

function B$dict($v, ignore_undef) {
    var instance = function ( ) {
        var args = Array.prototype.slice.call(arguments);
        if (arguments.callee['__class__'] === @{{instancemethod}}) {
            if (arguments.callee['im_self'] !== null) {
                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
            }
        }
        var a = @{{_getattr}}(arguments.callee, '__call__');
        if (typeof a == "undefined") {
            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
        }
        if (args.length >= 3) {
            var len = args.length;
            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
            }
        }
        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
    }
    instance['toString'] = function ( ) {
        try {
            return @{{mcall}}(this, null, this, '__str__').valueOf();
        } catch (e) {
        }
        try {
            return "<" + this.__class__.__name__ + " instance>";
        } catch (e) {
        }
        return "<instance>";
    };
    instance['$inst'] = true;
    instance['__class__'] = @{{dict}};
    instance['__object'] = {};
    instance['__object_hash'] = {};
    instance['__object_head'] = null;
    instance['__object_tail'] = null;
    instance['_length'] = 0;
    instance['valueOf'] = function() {return this.__object;};
    instance['getObject'] = function() {return this.__object;}; // backwards compatability TODO: remove this method
    instance['toString'] = function() {return this.__object.toString();};
    if (typeof $v != "undefined") {
        var h, k, v, node, head, tail, obj = instance['__object'], objH = instance['__object_hash'];
        head = tail = {'prev': null, 'next': null, 'key': null}
        for (k in $v) {
            v = $v[k];
            if (typeof k != "undefined" && typeof v != "undefined") {
                h = @{{hash}}(k);
                tail.next = node = {'prev': tail, 'next': null, 'key': k}
                tail = node;
                objH[h] = node;
                obj[h] = v;
                instance._length ++;
            } else {
                if (ignore_undef !== true) {
                    if (typeof k == "undefined") {
                        @{{raise}}($new(@{{TypeError}}, B$str("Invalid iterable (key is undefined)")));
                    }
                    @{{raise}}($new(@{{TypeError}}, B$str("Invalid iterable (value for '" + k + "' is undefined)")));
                }
            }
        }
        if (head !== tail) {
            instance.__object_head = head.next;
            instance.__object_head.prev = null;
            instance.__object_tail = tail;
        }
    }
    return instance;
};

function B$dictproxy($v) {
    if (typeof $v == "undefined") $v = {};
    var instance = function ( ) {
        var args = Array.prototype.slice.call(arguments);
        if (arguments.callee['__class__'] === @{{instancemethod}}) {
            if (arguments.callee['im_self'] !== null) {
                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
            }
        }
        var a = @{{_getattr}}(arguments.callee, '__call__');
        if (typeof a == "undefined") {
            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
        }
        if (args.length >= 3) {
            var len = args.length;
            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
            }
        }
        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
    }
    instance['toString'] = function ( ) {
        try {
            return @{{mcall}}(this, null, this, '__str__').valueOf();
        } catch (e) {
        }
        try {
            return "<" + this.__class__.__name__ + " instance>";
        } catch (e) {
        }
        return "<instance>";
    };
    instance['$inst'] = true;
    instance['__class__'] = @{{dictproxy}};
    instance['__object'] = $v;
    instance['valueOf'] = function() {return this.__object;};
    instance['toString'] = function() {return this.__object.toString();};
    return instance;
};

function B$list($v) {
    if (typeof $v == "undefined") $v = [];
    var instance = function ( ) {
        var args = Array.prototype.slice.call(arguments);
        if (arguments.callee['__class__'] === @{{instancemethod}}) {
            if (arguments.callee['im_self'] !== null) {
                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
            }
        }
        var a = @{{_getattr}}(arguments.callee, '__call__');
        if (typeof a == "undefined") {
            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
        }
        if (args.length >= 3) {
            var len = args.length;
            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
            }
        }
        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
    }
    instance['toString'] = function ( ) {
        try {
            return @{{mcall}}(this, null, this, '__str__').valueOf();
        } catch (e) {
        }
        try {
            return "<" + this.__class__.__name__ + " instance>";
        } catch (e) {
        }
        return "<instance>";
    };
    instance['$inst'] = true;
    instance['__class__'] = @{{list}};
    instance['__array'] = $v;
    instance['valueOf'] = function() {return this.__array;};
    instance['toString'] = function() {return this.__array.toString();};
    return instance;
};
@{{B$list}} = B$list;

function B$str($v) {
    if (typeof $v == "undefined") $v = "";
    var instance = function ( ) {
        var args = Array.prototype.slice.call(arguments);
        if (arguments.callee['__class__'] === @{{instancemethod}}) {
            if (arguments.callee['im_self'] !== null) {
                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
            }
        }
        var a = @{{_getattr}}(arguments.callee, '__call__');
        if (typeof a == "undefined") {
            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
        }
        if (args.length >= 3) {
            var len = args.length;
            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
            }
        }
        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
    }
    instance['toString'] = function ( ) {
        try {
            return @{{mcall}}(this, null, this, '__str__').valueOf();
        } catch (e) {
        }
        try {
            return "<" + this.__class__.__name__ + " instance>";
        } catch (e) {
        }
        return "<instance>";
    };
    instance['$inst'] = true;
    instance['__class__'] = @{{str}};
    instance['__s'] =  $v;
    instance['valueOf'] =  function() {return this.__s;};
    instance['toString'] =  function() {return this.__s.toString();};
    return instance;
};
@{{B$str}} = B$str;

function B$tuple($v) {
    if (typeof $v == "undefined") $v = [];
    var instance = function ( ) {
        var args = Array.prototype.slice.call(arguments);
        if (arguments.callee['__class__'] === @{{instancemethod}}) {
            if (arguments.callee['im_self'] !== null) {
                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
            }
        }
        var a = @{{_getattr}}(arguments.callee, '__call__');
        if (typeof a == "undefined") {
            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
        }
        if (args.length >= 3) {
            var len = args.length;
            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
            }
        }
        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
    }
    instance['toString'] = function ( ) {
        try {
            return @{{mcall}}(this, null, this, '__str__').valueOf();
        } catch (e) {
        }
        try {
            return "<" + this.__class__.__name__ + " instance>";
        } catch (e) {
        }
        return "<instance>";
    };
    instance['$inst'] = true;
    instance['__class__'] = @{{tuple}};
    instance['__array'] =  $v;
    instance['valueOf'] =  function() {return this.__array;};
    instance['toString'] =  function() {return this['__class__']['$dict']['__str__'](this).valueOf();};
    return instance;
};
@{{B$tuple}} = B$tuple;


/*
To create  valid type, we depend on the existance of:
 - object type (which is the base in all __mro__
 - tuple type (to create __bases__)
 - dictproxy type (to create the class __dict__)
 - the type type (is always in the class __class__)
 - the module type (is used in the type creation)
 - the basestring and str type (needed for class __name__)
 - the classmethod type (is used for the class __call__)
Not that in python the method-wrapper class is used for
class.__call__ (but seems to do the same as classmethod)

Therefore we'll do:
 - Create object type with tmp_type
 - Create tuple type with tmp_type
 - Create dictproxy type with tmp_type
 - Create type type with tmp_type
 - Create module type with tmp_type
 - Create basestring type with tmp_type
 - Create str type with tmp_type
 - Create classmethod type with tmp_type

Since we have the B$tuple and the B$str function, we can now:
 - Replace the __bases__ of the types with a tuple
 - Replace the __dict__ of the types with a dictproxy
 - Replace the __name__ of the types with a str
 - Add __class__ to the types
 - Add __call__ to the types
 - Remove tmp_type and use type for the rest of the code
   without implementing the complet tuple type yet.
*/

// We'll use the javascript Function as fuction class/instance
@{{function}} = Function;

@{{object}} = tmp_type(m$, 'object', [], {});
var B$__new__ = func(m$, null, @{{object}}, '__new__', 0, ['cls'], 'args', 'kwargs', null, function($cls) {
    var instance = function ( ) {
        var args = Array.prototype.slice.call(arguments);
        if (arguments.callee['__class__'] === @{{instancemethod}}) {
            if (arguments.callee['im_self'] !== null) {
                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
            }
        }
        var a = @{{_getattr}}(arguments.callee, '__call__');
        if (typeof a == "undefined") {
            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
        }
        if (args.length >= 3) {
            var len = args.length;
            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
            }
        }
        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
    }
    instance['toString'] = function ( ) {
        try {
            return @{{mcall}}(this, null, this, '__str__').valueOf();
        } catch (e) {
        }
        try {
            return "<" + this.__class__.__name__ + " instance>";
        } catch (e) {
        }
        return "<instance>";
    };
    instance['$inst'] = true;
    if (typeof $cls == "undefined") {
        debugger;
    }
    if (typeof $cls['__slots__'] == "undefined" || $cls['__slots__'].length > 0) {
        instance['__dict__'] = B$dict();
        instance['$dict'] = instance['__dict__']['__object'];
    }
    instance['__class__'] = $cls;
    return instance;
});
@{{tuple}} = tmp_type(m$, 'tuple', [@{{object}}], {});
@{{dictproxy}} = tmp_type(m$, 'dictproxy', [@{{object}}], {});
@{{type}} = tmp_type(m$, 'type', [@{{object}}], {});
m$['__class__'] = @{{module}} = tmp_type(m$, 'module', [@{{object}}], {});
@{{basestring}} = tmp_type(m$, 'basestring', [@{{object}}], {});
@{{str}} = tmp_type(m$, 'str', [@{{basestring}}], {});
@{{classmethod}} = tmp_type(m$, 'classmethod', [@{{object}}], {});
delete tmp_type;

// Some basic functions (some of them are needed very early (like _getattr)

// The use of stopiter depends on the single threaded nature of javascript
@{{stopiter}} = false;
@{{noraise}} = null;
func(m$, null, g$, 'raise', 1, ['cls', 'value', 'tb'], null, null, [null, null, null], function($cls, $value, $tb) {
    var exc = null;
    if (@{{stopiter}}) {
        @{{stopiter}} = false;
        if ($cls === @{{StopIteration}} || $cls['__class__'] === @{{StopIteration}}) {
            return @{{StopIter}};
        }
    }
    if (typeof $value == "undefined") {
        $value = null;
    }
    if (typeof $tb == "undefined") {
        $tb = null;
    }
    if (@{{noraise}} !== null) {
        if (@{{noraise}} === $cls || @{{noraise}} === $cls['__class__']) {
            $cls = @{{noraise}};
            @{{noraise}} = null;
            return $cls;
        }
    }
    if ($cls === null || typeof $cls == "undefined") {
        // re-raise last exception
    } else if ($value === null || $value.valueOf() === null) {
        if ($cls['$inst'] === true) {
            $pyjs.__last_exception__=  $cls;
        } else {
            $pyjs.__last_exception__ = $new($cls);
        }
    } else if ($cls['$inst'] === true) {
        if ($value.valueOf() === null) {
            $pyjs.__last_exception__= $cls;
        }
        $pyjs.__last_exception__ = $new(@{{TypeError}}, B$str("instance exception may not have a separate value"));
    } else if ($cls['$inst'] !== false) {
        $pyjs.__last_exception__ = $new(@{{TypeError}}, B$str("exceptions must be old-style classes or derived from BaseException"));
    } else {
        var mro;
        $pyjs.__last_exception__ = null;
        if ($value['$inst'] === true) {
            mro = $value['__class__']['__mro__'];
            for (var i = 0; i < mro.length; i++) {
                if (mro[i] === @{{tuple}}) {
                    mro = [$cls];
                    mro = mro.concat($value.__array);
                    $pyjs.__last_exception__ = inst.apply($cls, mro);
                }
            }
        }
        if ($pyjs.__last_exception__ === null) {
            $pyjs.__last_exception__ = $new($cls, $value);
        }
    }
    throw $pyjs.__last_exception__;
});

func(m$, null, g$, 'setattr', 1, ['obj', 'name', 'value'], null, null, null, function($obj, $name, $value) {
    var attr, __setattr__, __set__, mro, slots, retval, obj,
        attrname = typeof $name['__s'] != "undefined" ? attrname = $name['__s'] : attrname = $name.valueOf();
    if (attrname instanceof Array) {
        // internal use : setattr(obj, [attr, ...], value)
        // return value in stead of None
        retval = $value;
        if (attrname.length == 1) {
            attrname = attrname[0];
        } else {
            $obj = @{{getattr}}($obj, attrname.slice(0, attrname.length - 1));
            attrname = attrname[attrname.length - 1];
        }
    } else {
        retval = N$;
    }
    if (typeof attrname != 'string') {
        return @{{raise}}($new(@{{TypeError}}, B$str("attribute name must be string, not '" + _typeof($name) + "'")));
    }
    if ($obj['$inst'] === false ||  $obj['__class__'] === @{{module}}) {
        obj = $obj['$dict'];
        if ($value['__class__'] === @{{instancemethod}}) {
            $value = $value['im_func'];
        }
    } else if ($obj['$inst'] === true) {
        mro = $obj['__class__']['__mro__'];
        // Check for __set__ (@property)
        attr = typeof $obj['$dict'] != "undefined" ? $obj['$dict'][$name] : [][1];
        if (typeof attr == "undefined") {
            for (var i = 0; i < mro.length; i++) {
                attr = mro[i][$name];
                if (typeof attr == "undefined") {
                    attr = mro[i]['$dict'][$name];
                    if (typeof attr == "undefined") {
                        continue;
                    }
                }
                break;
            }
        }
        if (typeof attr != "undefined" && attr['$inst'] === true) {
            attr = @{{_getattr}}(attr, '__set__');
            if (typeof attr != "undefined") {
                return @{{fcall}}(this, null, attr, null, $obj, $value);
            }
        }
        slots = mro[0]['__slots__'];
        if (typeof slots != "undefined") {
            if (!(slots instanceof Array)) {
                slots = slots.__array instanceof Array ? slots.__array : [];
            }
            if (slots.indexOf(attrname) < 0) {
                return @{{raise}}($new(@{{AttributeError}}, B$str("'" + $obj.__class__.__name__ + "' object has no attribute '" + attrname + "'")));
            }
            if (typeof $obj['__class__']['$dict'][attrname] != 'undefined') {
                return @{{raise}}($new(@{{AttributeError}}, B$str("'" + $obj.__class__.__name__ + "' object attribute '" + attrname + "' is read-only")));
            }
            obj = $obj['$dict'];
        } else {
            // Check for __setattr__
            for (var i = 0; i < mro.length - 1; i++) { // length - 1: last is always object, which we won't call but handle here
                __setattr__ = mro[i]['__setattr__'];
                if (typeof __setattr__ == "undefined") {
                    __setattr__ = mro[i]['$dict']['__setattr__'];
                    if (typeof __setattr__ == "undefined") {
                        continue;
                    }
                }
                return mcall(this, null, $obj, '__setattr__', $name, $value);
            }
            dict$setitem($obj['__dict__'], attrname, $value);
            return retval;
        }
    }
    obj[attrname] = $value;
    return retval;
});

func(m$, null, g$, 'delattr', 1, ['obj', 'name'], null, null, null, function($obj, $name) {
    var attr, __delattr__,  __delete__, mro, obj,
        attrname = typeof $name['__s'] != "undefined" ? attrname = $name['__s'] : attrname = $name.valueOf();
    if (typeof attrname != 'string') {
        return @{{raise}}($new(@{{TypeError}}, B$str("attribute name must be string, not '" + _typeof($name) + "'")));
    }
    if ($obj['$inst'] === false ||  $obj['__class__'] === @{{module}}) {
        obj = $obj['$dict'];
    } else if ($obj['$inst'] === true) {
        mro = $obj['__class__']['__mro__'];
        // Check for __delete__ (@property)
        attr = typeof $obj['$dict'] != "undefined" ? $obj['$dict'][$name] : [][1];
        if (typeof attr == "undefined") {
            for (var i = 0; i < mro.length; i++) {
                attr = mro[i][$name];
                if (typeof attr == "undefined") {
                    attr = mro[i]['$dict'][$name];
                    if (typeof attr == "undefined") {
                        continue;
                    }
                }
                break;
            }
        }
        if (typeof attr != "undefined" && attr['$inst'] === true) {
            attr = @{{_getattr}}(attr, '__delete__');
            if (typeof attr != "undefined") {
                return @{{fcall}}(this, null, attr, null, $obj);
            }
        }
        slots = mro[0]['__slots__'];
        if (typeof slots != "undefined") {
            if (!(slots instanceof Array)) {
                slots = slots.__array instanceof Array ? slots.__array : [];
            }
            if (slots.indexOf(attrname) < 0) {
                return @{{raise}}($new(@{{AttributeError}}, B$str("'" + $obj.__class__.__name__ + "' object has no attribute '" + attrname + "'")));
            }
            if (typeof $obj['__class__']['$dict'][attrname] != 'undefined') {
                return @{{raise}}($new(@{{AttributeError}}, B$str("'" + $obj.__class__.__name__ + "' object attribute '" + attrname + "' is read-only")));
            }
            obj = $obj['$dict'];
        } else {
            // Check for __delattr__
            for (var i = 0; i < mro.length - 1; i++) { // length - 1: last is always object, which we won't call but handle here
                __delattr__ = mro[i]['__delattr__'];
                if (typeof __delattr__ == "undefined") {
                    __delattr__ = mro[i]['$dict']['__delattr__'];
                    if (typeof __delattr__ == "undefined") {
                        continue;
                    }
                }
                return mcall(this, null, $obj, '__delattr__', $name, $value);
            }
            if (typeof $obj['$dict'][attrname] == "undefined") {
                return @{{raise}}($new(@{{AttributeError}}, B$str($obj['__class__']['__name__'] + " instance has no attribute '" + $name + "'")));
            }
            dict$delitem($obj['__dict__'], attrname);
            return N$;
        }
    }
    if (typeof obj == "undefined" || typeof obj[attrname] == "undefined") {
        if ($obj['$inst'] === true) {
            return @{{raise}}($new(@{{AttributeError}}, B$str("'" + $obj['__class__']['__name__'] + "' object has no attribute '" + $name + "'")));
        }
        return @{{raise}}($new(@{{AttributeError}}, B$str(attrname)));
    }
    delete obj[attrname];
    return N$;
});

func(m$, null, g$, '_getattr', 1, ['obj', 'name'], null, null, null, function($obj, $name) {
    var v, mro$, names$;
    v = [][1];
    var mro$ = $obj['__mro__'];
    var _meth_src = $obj;
    switch ($obj['$inst']) {
        case true:
            if ($obj['__class__'] === @{{module}}) {
                v = $obj['$dict'][$name];
                break;
            } else if ($obj['__class__'] === @{{function}}) {
                switch ($name.charAt(0)) {
                    case 'i':
                    case '_':
                        v = $obj[$name];
                }
                break;
            }
            var _noraise$ = @{{noraise}};
            var ga;
            mro$ = $obj['__class__']['__mro__'];
            for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                var _mro$ = mro$[mro_i$];
                var ga = _mro$['__getattribute__'];
                if (typeof ga == "undefined") {
                    if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                        continue;
                    }
                    ga = _mro$['$dict']['__getattribute__'];
                }
                if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                    switch (ga['__class__']) {
                        case @{{function}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            _new_dst$['im_func'] = ga;
                            _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                            ga = _new_dst$;
                            break;
                        case @{{staticmethod}}:
                            ga = ga['im_func'];
                            break;
                        case @{{classmethod}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            _new_dst$['im_func'] = ga['im_func'];
                            _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            ga = _new_dst$;
                            break;
                        case @{{bool}}: // Some known to be non-descriptors
                        case @{{int}}:
                        case @{{long}}:
                        case @{{str}}:
                            break;
                        default:
                            // check for __get__ method in ga
                            if (ga['$inst'] === true) {
                                var get$ = @{{_getattr}}(ga, '__get__');
                                if (typeof get$ != 'undefined') {
                                    ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                }
                            }
                            break;
                    }
                }
                @{{noraise}} = @{{AttributeError}};
                v = @{{fcall}}(this, null, ga, _mro$, $name);
                @{{noraise}} = _noraise$;
                if (v === @{{AttributeError}}) {
                    v = [][1];
                }
                _meth_src = $obj['__class__'];
                $obj = $obj['__class__'];
                break;
            }
            if (typeof v == "undefined") {
                if (typeof $obj['$dict'] != "undefined") {
                    v = $obj['$dict'][$name];
                    if (typeof v != "undefined") {
                        if (v !== {}[$name]) {
                            break;
                        }
                        v = [][1];
                    }
                }
                switch ($name.charAt(0)) {
                    case 'i':
                    case '_':
                        v = $obj[$name];
                }
                if (typeof v != "undefined") {
                    break;
                }
            }
        case false:
            if (typeof v == "undefined") {
                var _mro$, ga;
                if ($obj['$inst'] === true) {
                    _meth_src = $obj['__class__'];
                } else {
                    switch ($name.charAt(0)) {
                        case 'i':
                        case '_':
                            v = $obj[$name];
                    }
                    if (typeof v != "undefined") {
                        break;
                    }

                }
                if (typeof v == "undefined") {
                    for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        v = _mro$['$dict'][$name];
                        if (typeof v != "undefined") {
                            if (v !== {}[$name]) {
                                break;
                            }
                            v = [][1];
                        }
                        switch ($name.charAt(0)) {
                            case 'i':
                            case '_':
                                v = _mro$[$name];
                        }
                        if (typeof v != "undefined") {
                            break;
                        }
                    }
                }
                if (typeof v == "undefined" && $name !== '__get__') {
                    for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattr__'];
                        if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                            switch (ga['__class__']) {
                                case @{{function}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    _new_dst$['im_func'] = ga;
                                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                                    ga = _new_dst$;
                                    break;
                                case @{{staticmethod}}:
                                    ga = ga['im_func'];
                                    break;
                                case @{{classmethod}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    _new_dst$['im_func'] = ga['im_func'];
                                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    ga = _new_dst$;
                                    break;
                                case @{{bool}}: // Some known to be non-descriptors
                                case @{{int}}:
                                case @{{long}}:
                                case @{{str}}:
                                    break;
                                default:
                                    // check for __get__ method in ga
                                    if (ga['$inst'] === true) {
                                        var get$ = @{{_getattr}}(ga, '__get__');
                                        if (typeof get$ != 'undefined') {
                                            ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                        }
                                    }
                                    break;
                            }
                        }
                        @{{noraise}} = @{{AttributeError}};
                        v = @{{fcall}}(this, null, ga, _mro$, $name);
                        @{{noraise}} = _noraise$;
                        if (v === @{{AttributeError}}) {
                            v = [][1];
                        }
                        // TODO : unbind v ?
                        break;
                    }
                }
            }
            break;
        default:
            v = $obj[$name];
            if (typeof v == "undefined" && typeof $obj['$dict'] != "undefined") {
                v = $obj['$dict'][$name];
            }
    }
    if (_meth_src['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof v != "undefined" && typeof v['$inst'] != "undefined") {
        switch (v['__class__']) {
            case @{{function}}:
                var _new_dst$ = function ( ) {
                    var args = Array.prototype.slice.call(arguments);
                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                        if (arguments.callee['im_self'] !== null) {
                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                        }
                    }
                    var a = @{{_getattr}}(arguments.callee, '__call__');
                    if (typeof a == "undefined") {
                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                    }
                    if (args.length >= 3) {
                        var len = args.length;
                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                    }
                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                }
                _new_dst$['toString'] = function ( ) {
                    try {
                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                    } catch (e) {
                    }
                    try {
                        return "<" + this.__class__.__name__ + " instance>";
                    } catch (e) {
                    }
                    return "<instance>";
                };
                _new_dst$['$inst'] = true;
                if (typeof @{{instancemethod}} == "undefined") {
                    debugger;
                }
                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                    _new_dst$['__dict__'] = B$dict();
                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                }
                _new_dst$['__class__'] = @{{instancemethod}};
                _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                _new_dst$['im_func'] = v;
                _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                v = _new_dst$;
                break;
            case @{{staticmethod}}:
                v = v['im_func'];
                break;
            case @{{classmethod}}:
                var _new_dst$ = function ( ) {
                    var args = Array.prototype.slice.call(arguments);
                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                        if (arguments.callee['im_self'] !== null) {
                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                        }
                    }
                    var a = @{{_getattr}}(arguments.callee, '__call__');
                    if (typeof a == "undefined") {
                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                    }
                    if (args.length >= 3) {
                        var len = args.length;
                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                    }
                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                }
                _new_dst$['toString'] = function ( ) {
                    try {
                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                    } catch (e) {
                    }
                    try {
                        return "<" + this.__class__.__name__ + " instance>";
                    } catch (e) {
                    }
                    return "<instance>";
                };
                _new_dst$['$inst'] = true;
                if (typeof @{{instancemethod}} == "undefined") {
                    debugger;
                }
                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                    _new_dst$['__dict__'] = B$dict();
                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                }
                _new_dst$['__class__'] = @{{instancemethod}};
                _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                _new_dst$['im_func'] = v['im_func'];
                _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                v = _new_dst$;
                break;
            case @{{bool}}: // Some known to be non-descriptors
            case @{{int}}:
            case @{{long}}:
            case @{{str}}:
                break;
            default:
                // check for __get__ method in v
                if (v['$inst'] === true) {
                    var get$ = @{{_getattr}}(v, '__get__');
                    if (typeof get$ != 'undefined') {
                        v = @{{fcall}}(this, null, get$, v, $obj, $obj['__class__']);
                    }
                }
                break;
        }
    }
    return v;
});

func(m$, null, g$, 'getattr', 1, ['obj', 'name', 'value'], null, null, [null], function($obj, $name, $value) {
    var attr, obj = $obj;
    var attrname, attrnames, ga, mro, _obj = obj;
    if ($name instanceof Array) {
        attrnames = $name;
    } else {
        attrnames = [$name];
    }
    find_attr:
    for (var attri = 0; attri < attrnames.length; attri++) {
        attrname = attrnames[attri];
        if (typeof attrname != 'string') {
            if (typeof attrname['__s'] != "undefined") {
                attrname = attrname['__s'];
            } else {
                @{{raise}}($new(@{{TypeError}}, B$str("attribute name must be string, not '" + _typeof(attrname) + "'")));
            }
        }
        attr = [][1];
        var mro = _obj['__mro__'];
        var _meth_src = _obj;
        switch (_obj['$inst']) {
            case true:
                if (_obj['__class__'] === @{{module}}) {
                    attr = _obj['$dict'][attrname];
                    break;
                } else if (_obj['__class__'] === @{{function}}) {
                    switch (attrname.charAt(0)) {
                        case 'i':
                        case '_':
                            attr = _obj[attrname];
                    }
                    break;
                }
                var _noraise$ = @{{noraise}};
                var ga;
                mro = _obj['__class__']['__mro__'];
                for (var mro_i$ = 0; mro_i$ < mro.length - 1; mro_i$++) {
                    var _mro$ = mro[mro_i$];
                    var ga = _mro$['__getattribute__'];
                    if (typeof ga == "undefined") {
                        if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattribute__'];
                    }
                    if (_obj['__class__']['$inst'] === false && _obj['__class__'] !== @{{module}} && typeof _obj != "undefined" && typeof _obj['$inst'] != "undefined") {
                        switch (ga['__class__']) {
                            case @{{function}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                _new_dst$['im_func'] = ga;
                                _new_dst$['im_self'] = _obj['$inst'] === true ? _obj : null;
                                ga = _new_dst$;
                                break;
                            case @{{staticmethod}}:
                                ga = ga['im_func'];
                                break;
                            case @{{classmethod}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                _new_dst$['im_func'] = ga['im_func'];
                                _new_dst$['im_self'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                ga = _new_dst$;
                                break;
                            case @{{bool}}: // Some known to be non-descriptors
                            case @{{int}}:
                            case @{{long}}:
                            case @{{str}}:
                                break;
                            default:
                                // check for __get__ method in ga
                                if (ga['$inst'] === true) {
                                    var get$ = @{{_getattr}}(ga, '__get__');
                                    if (typeof get$ != 'undefined') {
                                        ga = @{{fcall}}(this, null, get$, ga, _obj, _obj['__class__']);
                                    }
                                }
                                break;
                        }
                    }
                    @{{noraise}} = @{{AttributeError}};
                    attr = @{{fcall}}(this, null, ga, _mro$, attrname);
                    @{{noraise}} = _noraise$;
                    if (attr === @{{AttributeError}}) {
                        attr = [][1];
                    }
                    _meth_src = _obj['__class__'];
                    _obj = _obj['__class__'];
                    break;
                }
                if (typeof attr == "undefined") {
                    if (typeof _obj['$dict'] != "undefined") {
                        attr = _obj['$dict'][attrname];
                        if (typeof attr != "undefined") {
                            if (attr !== {}[attrname]) {
                                break;
                            }
                            attr = [][1];
                        }
                    }
                    switch (attrname.charAt(0)) {
                        case 'i':
                        case '_':
                            attr = _obj[attrname];
                    }
                    if (typeof attr != "undefined") {
                        break;
                    }
                }
            case false:
                if (typeof attr == "undefined") {
                    var _mro$, ga;
                    if (_obj['$inst'] === true) {
                        _meth_src = _obj['__class__'];
                    } else {
                        switch (attrname.charAt(0)) {
                            case 'i':
                            case '_':
                                attr = _obj[attrname];
                        }
                        if (typeof attr != "undefined") {
                            break;
                        }

                    }
                    if (typeof attr == "undefined") {
                        for (var mro_i$ = 0; mro_i$ < mro.length; mro_i$++) {
                            _mro$ = mro[mro_i$];
                            attr = _mro$['$dict'][attrname];
                            if (typeof attr != "undefined") {
                                if (attr !== {}[attrname]) {
                                    break;
                                }
                                attr = [][1];
                            }
                            switch (attrname.charAt(0)) {
                                case 'i':
                                case '_':
                                    attr = _mro$[attrname];
                            }
                            if (typeof attr != "undefined") {
                                break;
                            }
                        }
                    }
                    if (typeof attr == "undefined" && attrname !== '__get__') {
                        for (var mro_i$ = 0; mro_i$ < mro.length - 1; mro_i$++) {
                            _mro$ = mro[mro_i$];
                            if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                continue;
                            }
                            ga = _mro$['$dict']['__getattr__'];
                            if (_obj['__class__']['$inst'] === false && _obj['__class__'] !== @{{module}} && typeof _obj != "undefined" && typeof _obj['$inst'] != "undefined") {
                                switch (ga['__class__']) {
                                    case @{{function}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                        _new_dst$['im_func'] = ga;
                                        _new_dst$['im_self'] = _obj['$inst'] === true ? _obj : null;
                                        ga = _new_dst$;
                                        break;
                                    case @{{staticmethod}}:
                                        ga = ga['im_func'];
                                        break;
                                    case @{{classmethod}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                        _new_dst$['im_func'] = ga['im_func'];
                                        _new_dst$['im_self'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                                        ga = _new_dst$;
                                        break;
                                    case @{{bool}}: // Some known to be non-descriptors
                                    case @{{int}}:
                                    case @{{long}}:
                                    case @{{str}}:
                                        break;
                                    default:
                                        // check for __get__ method in ga
                                        if (ga['$inst'] === true) {
                                            var get$ = @{{_getattr}}(ga, '__get__');
                                            if (typeof get$ != 'undefined') {
                                                ga = @{{fcall}}(this, null, get$, ga, _obj, _obj['__class__']);
                                            }
                                        }
                                        break;
                                }
                            }
                            @{{noraise}} = @{{AttributeError}};
                            attr = @{{fcall}}(this, null, ga, _mro$, attrname);
                            @{{noraise}} = _noraise$;
                            if (attr === @{{AttributeError}}) {
                                attr = [][1];
                            }
                            // TODO : unbind attr ?
                            break;
                        }
                    }
                }
                break;
            default:
                attr = _obj[attrname];
                if (typeof attr == "undefined" && typeof _obj['$dict'] != "undefined") {
                    attr = _obj['$dict'][attrname];
                }
        }
        if (typeof attr == "undefined") {
            if (_obj['$inst'] === true && _obj['__class__'] !== @{{module}} && _obj['__class__'] !== @{{function}}) {
                if (typeof attr == "undefined") {
                    if ($value === null || typeof $value == "undefined") {
                        @{{raise}}($new(@{{AttributeError}}, B$str("'" + _obj['__class__']['__name__'] + "' object has no attribute '" + attrname + "'")));
                    } else {
                        attr = $value;
                        break find_attr;
                    }
                }
            }
            if ($value === null || typeof $value == "undefined") {
                if (_obj['$inst'] === false) {
                    @{{raise}}($new(@{{AttributeError}}, B$str("type object '" + _obj['__name__'] + "' object has no attribute '" + attrname + "'")));
                }
                @{{raise}}($new(@{{AttributeError}}, B$str(attrname)));
            }
            attr = $value;
            break find_attr;
        }
        if (attri == attrnames.length - 1) {
            if (_meth_src['$inst'] === false && _obj['__class__'] !== @{{module}} && typeof _obj != "undefined" && typeof _obj['$inst'] != "undefined") {
                switch (attr['__class__']) {
                    case @{{function}}:
                        var _new_dst$ = function ( ) {
                            var args = Array.prototype.slice.call(arguments);
                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                if (arguments.callee['im_self'] !== null) {
                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                }
                            }
                            var a = @{{_getattr}}(arguments.callee, '__call__');
                            if (typeof a == "undefined") {
                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                            }
                            if (args.length >= 3) {
                                var len = args.length;
                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                            }
                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                        _new_dst$['toString'] = function ( ) {
                            try {
                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                            } catch (e) {
                            }
                            try {
                                return "<" + this.__class__.__name__ + " instance>";
                            } catch (e) {
                            }
                            return "<instance>";
                        };
                        _new_dst$['$inst'] = true;
                        if (typeof @{{instancemethod}} == "undefined") {
                            debugger;
                        }
                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                            _new_dst$['__dict__'] = B$dict();
                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                        }
                        _new_dst$['__class__'] = @{{instancemethod}};
                        _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                        _new_dst$['im_func'] = attr;
                        _new_dst$['im_self'] = _obj['$inst'] === true ? _obj : null;
                        attr = _new_dst$;
                        break;
                    case @{{staticmethod}}:
                        attr = attr['im_func'];
                        break;
                    case @{{classmethod}}:
                        var _new_dst$ = function ( ) {
                            var args = Array.prototype.slice.call(arguments);
                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                if (arguments.callee['im_self'] !== null) {
                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                }
                            }
                            var a = @{{_getattr}}(arguments.callee, '__call__');
                            if (typeof a == "undefined") {
                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                            }
                            if (args.length >= 3) {
                                var len = args.length;
                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                            }
                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                        _new_dst$['toString'] = function ( ) {
                            try {
                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                            } catch (e) {
                            }
                            try {
                                return "<" + this.__class__.__name__ + " instance>";
                            } catch (e) {
                            }
                            return "<instance>";
                        };
                        _new_dst$['$inst'] = true;
                        if (typeof @{{instancemethod}} == "undefined") {
                            debugger;
                        }
                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                            _new_dst$['__dict__'] = B$dict();
                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                        }
                        _new_dst$['__class__'] = @{{instancemethod}};
                        _new_dst$['im_class'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                        _new_dst$['im_func'] = attr['im_func'];
                        _new_dst$['im_self'] = _obj['$inst'] === true ? _obj['__class__'] : _obj;
                        attr = _new_dst$;
                        break;
                    case @{{bool}}: // Some known to be non-descriptors
                    case @{{int}}:
                    case @{{long}}:
                    case @{{str}}:
                        break;
                    default:
                        // check for __get__ method in attr
                        if (attr['$inst'] === true) {
                            var get$ = @{{_getattr}}(attr, '__get__');
                            if (typeof get$ != 'undefined') {
                                attr = @{{fcall}}(this, null, get$, attr, _obj, _obj['__class__']);
                            }
                        }
                        break;
                }
            }
        } else {
            // check for __get__ method in attr
            if (attr['$inst'] === true) {
                var get$ = @{{_getattr}}(attr, '__get__');
                if (typeof get$ != 'undefined') {
                    attr = @{{fcall}}(this, null, get$, attr, _obj, _obj['__class__']);
                }
            }
        }
        obj = _obj;
        _obj = attr;
    }
    return attr;
});

func(m$, null, g$, 'hasattr', 1, ['obj', 'name'], null, null, null, function($obj, $name) {
    var v, mro$, names$;
    if (typeof $name != 'string') {
        if (typeof $name.__s == "undefined") {
            return @{{raise}}($new(@{{TypeError}}, B$str("attribute name must be string, not '" + _typeof($name) + "'")));
        }
        $name = $name.valueOf()
    }
    v = [][1];
    var mro$ = $obj['__mro__'];
    var _meth_src = $obj;
    switch ($obj['$inst']) {
        case true:
            if ($obj['__class__'] === @{{module}}) {
                v = $obj['$dict'][$name];
                break;
            } else if ($obj['__class__'] === @{{function}}) {
                switch ($name.charAt(0)) {
                    case 'i':
                    case '_':
                        v = $obj[$name];
                }
                break;
            }
            var _noraise$ = @{{noraise}};
            var ga;
            mro$ = $obj['__class__']['__mro__'];
            for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                var _mro$ = mro$[mro_i$];
                var ga = _mro$['__getattribute__'];
                if (typeof ga == "undefined") {
                    if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                        continue;
                    }
                    ga = _mro$['$dict']['__getattribute__'];
                }
                if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                    switch (ga['__class__']) {
                        case @{{function}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            _new_dst$['im_func'] = ga;
                            _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                            ga = _new_dst$;
                            break;
                        case @{{staticmethod}}:
                            ga = ga['im_func'];
                            break;
                        case @{{classmethod}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            _new_dst$['im_func'] = ga['im_func'];
                            _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            ga = _new_dst$;
                            break;
                        case @{{bool}}: // Some known to be non-descriptors
                        case @{{int}}:
                        case @{{long}}:
                        case @{{str}}:
                            break;
                        default:
                            // check for __get__ method in ga
                            if (ga['$inst'] === true) {
                                var get$ = @{{_getattr}}(ga, '__get__');
                                if (typeof get$ != 'undefined') {
                                    ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                }
                            }
                            break;
                    }
                }
                @{{noraise}} = @{{AttributeError}};
                v = @{{fcall}}(this, null, ga, _mro$, $name);
                @{{noraise}} = _noraise$;
                if (v === @{{AttributeError}}) {
                    v = [][1];
                }
                _meth_src = $obj['__class__'];
                $obj = $obj['__class__'];
                break;
            }
            if (typeof v == "undefined") {
                if (typeof $obj['$dict'] != "undefined") {
                    v = $obj['$dict'][$name];
                    if (typeof v != "undefined") {
                        if (v !== {}[$name]) {
                            break;
                        }
                        v = [][1];
                    }
                }
                switch ($name.charAt(0)) {
                    case 'i':
                    case '_':
                        v = $obj[$name];
                }
                if (typeof v != "undefined") {
                    break;
                }
            }
        case false:
            if (typeof v == "undefined") {
                var _mro$, ga;
                if ($obj['$inst'] === true) {
                    _meth_src = $obj['__class__'];
                } else {
                    switch ($name.charAt(0)) {
                        case 'i':
                        case '_':
                            v = $obj[$name];
                    }
                    if (typeof v != "undefined") {
                        break;
                    }

                }
                if (typeof v == "undefined") {
                    for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        v = _mro$['$dict'][$name];
                        if (typeof v != "undefined") {
                            if (v !== {}[$name]) {
                                break;
                            }
                            v = [][1];
                        }
                        switch ($name.charAt(0)) {
                            case 'i':
                            case '_':
                                v = _mro$[$name];
                        }
                        if (typeof v != "undefined") {
                            break;
                        }
                    }
                }
                if (typeof v == "undefined" && $name !== '__get__') {
                    for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattr__'];
                        if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                            switch (ga['__class__']) {
                                case @{{function}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    _new_dst$['im_func'] = ga;
                                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                                    ga = _new_dst$;
                                    break;
                                case @{{staticmethod}}:
                                    ga = ga['im_func'];
                                    break;
                                case @{{classmethod}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    _new_dst$['im_func'] = ga['im_func'];
                                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    ga = _new_dst$;
                                    break;
                                case @{{bool}}: // Some known to be non-descriptors
                                case @{{int}}:
                                case @{{long}}:
                                case @{{str}}:
                                    break;
                                default:
                                    // check for __get__ method in ga
                                    if (ga['$inst'] === true) {
                                        var get$ = @{{_getattr}}(ga, '__get__');
                                        if (typeof get$ != 'undefined') {
                                            ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                        }
                                    }
                                    break;
                            }
                        }
                        @{{noraise}} = @{{AttributeError}};
                        v = @{{fcall}}(this, null, ga, _mro$, $name);
                        @{{noraise}} = _noraise$;
                        if (v === @{{AttributeError}}) {
                            v = [][1];
                        }
                        // TODO : unbind v ?
                        break;
                    }
                }
            }
            break;
        default:
            v = $obj[$name];
            if (typeof v == "undefined" && typeof $obj['$dict'] != "undefined") {
                v = $obj['$dict'][$name];
            }
    }
    if (typeof v == 'undefined') {
        return @{{False}};
    }
    return @{{True}};
});

func(m$, null, g$, 'setitem', 1, ['obj', 'name', 'value'], null, null, null, function($obj, $name, $value) {
    var meth;
    meth = [][1];
    var mro$ = $obj['__mro__'];
    var _meth_src = $obj;
    switch ($obj['$inst']) {
        case true:
            if ($obj['__class__'] === @{{module}}) {
                meth = $obj['$dict']['__setitem__'];
                break;
            } else if ($obj['__class__'] === @{{function}}) {
                switch ('__setitem__'.charAt(0)) {
                    case 'i':
                    case '_':
                        meth = $obj['__setitem__'];
                }
                break;
            }
            var _noraise$ = @{{noraise}};
            var ga;
            mro$ = $obj['__class__']['__mro__'];
            for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                var _mro$ = mro$[mro_i$];
                var ga = _mro$['__getattribute__'];
                if (typeof ga == "undefined") {
                    if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                        continue;
                    }
                    ga = _mro$['$dict']['__getattribute__'];
                }
                if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                    switch (ga['__class__']) {
                        case @{{function}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            _new_dst$['im_func'] = ga;
                            _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                            ga = _new_dst$;
                            break;
                        case @{{staticmethod}}:
                            ga = ga['im_func'];
                            break;
                        case @{{classmethod}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            _new_dst$['im_func'] = ga['im_func'];
                            _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            ga = _new_dst$;
                            break;
                        case @{{bool}}: // Some known to be non-descriptors
                        case @{{int}}:
                        case @{{long}}:
                        case @{{str}}:
                            break;
                        default:
                            // check for __get__ method in ga
                            if (ga['$inst'] === true) {
                                var get$ = @{{_getattr}}(ga, '__get__');
                                if (typeof get$ != 'undefined') {
                                    ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                }
                            }
                            break;
                    }
                }
                @{{noraise}} = @{{AttributeError}};
                meth = @{{fcall}}(this, null, ga, _mro$, '__setitem__');
                @{{noraise}} = _noraise$;
                if (meth === @{{AttributeError}}) {
                    meth = [][1];
                }
                _meth_src = $obj['__class__'];
                $obj = $obj['__class__'];
                break;
            }
            if (typeof meth == "undefined") {
                if (typeof $obj['$dict'] != "undefined") {
                    meth = $obj['$dict']['__setitem__'];
                    if (typeof meth != "undefined") {
                        if (meth !== {}['__setitem__']) {
                            break;
                        }
                        meth = [][1];
                    }
                }
                switch ('__setitem__'.charAt(0)) {
                    case 'i':
                    case '_':
                        meth = $obj['__setitem__'];
                }
                if (typeof meth != "undefined") {
                    break;
                }
            }
        case false:
            if (typeof meth == "undefined") {
                var _mro$, ga;
                if ($obj['$inst'] === true) {
                    _meth_src = $obj['__class__'];
                } else {
                    switch ('__setitem__'.charAt(0)) {
                        case 'i':
                        case '_':
                            meth = $obj['__setitem__'];
                    }
                    if (typeof meth != "undefined") {
                        break;
                    }

                }
                if (typeof meth == "undefined") {
                    for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        meth = _mro$['$dict']['__setitem__'];
                        if (typeof meth != "undefined") {
                            if (meth !== {}['__setitem__']) {
                                break;
                            }
                            meth = [][1];
                        }
                        switch ('__setitem__'.charAt(0)) {
                            case 'i':
                            case '_':
                                meth = _mro$['__setitem__'];
                        }
                        if (typeof meth != "undefined") {
                            break;
                        }
                    }
                }
                if (typeof meth == "undefined" && '__setitem__' !== '__get__') {
                    for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattr__'];
                        if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                            switch (ga['__class__']) {
                                case @{{function}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    _new_dst$['im_func'] = ga;
                                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                                    ga = _new_dst$;
                                    break;
                                case @{{staticmethod}}:
                                    ga = ga['im_func'];
                                    break;
                                case @{{classmethod}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    _new_dst$['im_func'] = ga['im_func'];
                                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    ga = _new_dst$;
                                    break;
                                case @{{bool}}: // Some known to be non-descriptors
                                case @{{int}}:
                                case @{{long}}:
                                case @{{str}}:
                                    break;
                                default:
                                    // check for __get__ method in ga
                                    if (ga['$inst'] === true) {
                                        var get$ = @{{_getattr}}(ga, '__get__');
                                        if (typeof get$ != 'undefined') {
                                            ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                        }
                                    }
                                    break;
                            }
                        }
                        @{{noraise}} = @{{AttributeError}};
                        meth = @{{fcall}}(this, null, ga, _mro$, '__setitem__');
                        @{{noraise}} = _noraise$;
                        if (meth === @{{AttributeError}}) {
                            meth = [][1];
                        }
                        // TODO : unbind meth ?
                        break;
                    }
                }
            }
            break;
        default:
            meth = $obj['__setitem__'];
            if (typeof meth == "undefined" && typeof $obj['$dict'] != "undefined") {
                meth = $obj['$dict']['__setitem__'];
            }
    }
    if (typeof meth != "undefined") {
        if (_meth_src['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof meth != "undefined" && typeof meth['$inst'] != "undefined") {
            switch (meth['__class__']) {
                case @{{function}}:
                    var _new_dst$ = function ( ) {
                        var args = Array.prototype.slice.call(arguments);
                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                            if (arguments.callee['im_self'] !== null) {
                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                            }
                        }
                        var a = @{{_getattr}}(arguments.callee, '__call__');
                        if (typeof a == "undefined") {
                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                        }
                        if (args.length >= 3) {
                            var len = args.length;
                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                        }
                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                    }
                    _new_dst$['toString'] = function ( ) {
                        try {
                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                        } catch (e) {
                        }
                        try {
                            return "<" + this.__class__.__name__ + " instance>";
                        } catch (e) {
                        }
                        return "<instance>";
                    };
                    _new_dst$['$inst'] = true;
                    if (typeof @{{instancemethod}} == "undefined") {
                        debugger;
                    }
                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                        _new_dst$['__dict__'] = B$dict();
                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                    }
                    _new_dst$['__class__'] = @{{instancemethod}};
                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                    _new_dst$['im_func'] = meth;
                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                    meth = _new_dst$;
                    break;
                case @{{staticmethod}}:
                    meth = meth['im_func'];
                    break;
                case @{{classmethod}}:
                    var _new_dst$ = function ( ) {
                        var args = Array.prototype.slice.call(arguments);
                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                            if (arguments.callee['im_self'] !== null) {
                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                            }
                        }
                        var a = @{{_getattr}}(arguments.callee, '__call__');
                        if (typeof a == "undefined") {
                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                        }
                        if (args.length >= 3) {
                            var len = args.length;
                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                        }
                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                    }
                    _new_dst$['toString'] = function ( ) {
                        try {
                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                        } catch (e) {
                        }
                        try {
                            return "<" + this.__class__.__name__ + " instance>";
                        } catch (e) {
                        }
                        return "<instance>";
                    };
                    _new_dst$['$inst'] = true;
                    if (typeof @{{instancemethod}} == "undefined") {
                        debugger;
                    }
                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                        _new_dst$['__dict__'] = B$dict();
                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                    }
                    _new_dst$['__class__'] = @{{instancemethod}};
                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                    _new_dst$['im_func'] = meth['im_func'];
                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                    meth = _new_dst$;
                    break;
                case @{{bool}}: // Some known to be non-descriptors
                case @{{int}}:
                case @{{long}}:
                case @{{str}}:
                    break;
                default:
                    // check for __get__ method in meth
                    if (meth['$inst'] === true) {
                        var get$ = @{{_getattr}}(meth, '__get__');
                        if (typeof get$ != 'undefined') {
                            meth = @{{fcall}}(this, null, get$, meth, $obj, $obj['__class__']);
                        }
                    }
                    break;
            }
        }
        return @{{fcall}}(this, null, meth, $obj, $name, $value);
    }
    if (typeof $obj['$inst'] != "undefined") {
        return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof($obj) +"' object does not support item assignment")));
    }
    if (typeof $obj instanceof Array) {
        var idx = $name.valueOf();
        if (typeof idx == 'number') {
            $obj[idx] = $value;
            return $value;
        }
        return @{{raise}}($new(@{{TypeError}}, B$str("Javascript array needs number indexes not '" + _typeof($name) + "'")));
    }
    if (typeof $obj == 'object') {
        var name = $name.valueOf();
        if (typeof name == 'string') {
            $obj[name] = $value;
        } else {
            $obj[$name] = $value;
        }
        return $value;
    }
    return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof($obj) + "' does not support item assignment")));
});

func(m$, null, g$, 'setslice', 1, ['obj', 'slice', 'value'], null, null, null, function($obj, $slice, $value) {
    var meth, attrs = $slice.length == 2 ? ['__setslice__', '__setitem__'] : ['__setitem__'];
    for (var attri = 0 ; attri < attrs.length; attri++) {
        var attr = attrs[attri];
        meth = [][1];
        var mro$ = $obj['__mro__'];
        var _meth_src = $obj;
        switch ($obj['$inst']) {
            case true:
                if ($obj['__class__'] === @{{module}}) {
                    meth = $obj['$dict'][attr];
                    break;
                } else if ($obj['__class__'] === @{{function}}) {
                    switch (attr.charAt(0)) {
                        case 'i':
                        case '_':
                            meth = $obj[attr];
                    }
                    break;
                }
                var _noraise$ = @{{noraise}};
                var ga;
                mro$ = $obj['__class__']['__mro__'];
                for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                    var _mro$ = mro$[mro_i$];
                    var ga = _mro$['__getattribute__'];
                    if (typeof ga == "undefined") {
                        if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattribute__'];
                    }
                    if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                        switch (ga['__class__']) {
                            case @{{function}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                _new_dst$['im_func'] = ga;
                                _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                                ga = _new_dst$;
                                break;
                            case @{{staticmethod}}:
                                ga = ga['im_func'];
                                break;
                            case @{{classmethod}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                _new_dst$['im_func'] = ga['im_func'];
                                _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                ga = _new_dst$;
                                break;
                            case @{{bool}}: // Some known to be non-descriptors
                            case @{{int}}:
                            case @{{long}}:
                            case @{{str}}:
                                break;
                            default:
                                // check for __get__ method in ga
                                if (ga['$inst'] === true) {
                                    var get$ = @{{_getattr}}(ga, '__get__');
                                    if (typeof get$ != 'undefined') {
                                        ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                    }
                                }
                                break;
                        }
                    }
                    @{{noraise}} = @{{AttributeError}};
                    meth = @{{fcall}}(this, null, ga, _mro$, attr);
                    @{{noraise}} = _noraise$;
                    if (meth === @{{AttributeError}}) {
                        meth = [][1];
                    }
                    _meth_src = $obj['__class__'];
                    $obj = $obj['__class__'];
                    break;
                }
                if (typeof meth == "undefined") {
                    if (typeof $obj['$dict'] != "undefined") {
                        meth = $obj['$dict'][attr];
                        if (typeof meth != "undefined") {
                            if (meth !== {}[attr]) {
                                break;
                            }
                            meth = [][1];
                        }
                    }
                    switch (attr.charAt(0)) {
                        case 'i':
                        case '_':
                            meth = $obj[attr];
                    }
                    if (typeof meth != "undefined") {
                        break;
                    }
                }
            case false:
                if (typeof meth == "undefined") {
                    var _mro$, ga;
                    if ($obj['$inst'] === true) {
                        _meth_src = $obj['__class__'];
                    } else {
                        switch (attr.charAt(0)) {
                            case 'i':
                            case '_':
                                meth = $obj[attr];
                        }
                        if (typeof meth != "undefined") {
                            break;
                        }

                    }
                    if (typeof meth == "undefined") {
                        for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            meth = _mro$['$dict'][attr];
                            if (typeof meth != "undefined") {
                                if (meth !== {}[attr]) {
                                    break;
                                }
                                meth = [][1];
                            }
                            switch (attr.charAt(0)) {
                                case 'i':
                                case '_':
                                    meth = _mro$[attr];
                            }
                            if (typeof meth != "undefined") {
                                break;
                            }
                        }
                    }
                    if (typeof meth == "undefined" && attr !== '__get__') {
                        for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                continue;
                            }
                            ga = _mro$['$dict']['__getattr__'];
                            if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                                switch (ga['__class__']) {
                                    case @{{function}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                        _new_dst$['im_func'] = ga;
                                        _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                                        ga = _new_dst$;
                                        break;
                                    case @{{staticmethod}}:
                                        ga = ga['im_func'];
                                        break;
                                    case @{{classmethod}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                        _new_dst$['im_func'] = ga['im_func'];
                                        _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                        ga = _new_dst$;
                                        break;
                                    case @{{bool}}: // Some known to be non-descriptors
                                    case @{{int}}:
                                    case @{{long}}:
                                    case @{{str}}:
                                        break;
                                    default:
                                        // check for __get__ method in ga
                                        if (ga['$inst'] === true) {
                                            var get$ = @{{_getattr}}(ga, '__get__');
                                            if (typeof get$ != 'undefined') {
                                                ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                            }
                                        }
                                        break;
                                }
                            }
                            @{{noraise}} = @{{AttributeError}};
                            meth = @{{fcall}}(this, null, ga, _mro$, attr);
                            @{{noraise}} = _noraise$;
                            if (meth === @{{AttributeError}}) {
                                meth = [][1];
                            }
                            // TODO : unbind meth ?
                            break;
                        }
                    }
                }
                break;
            default:
                meth = $obj[attr];
                if (typeof meth == "undefined" && typeof $obj['$dict'] != "undefined") {
                    meth = $obj['$dict'][attr];
                }
        }
        if (typeof meth != "undefined") {
            if (_meth_src['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof meth != "undefined" && typeof meth['$inst'] != "undefined") {
                switch (meth['__class__']) {
                    case @{{function}}:
                        var _new_dst$ = function ( ) {
                            var args = Array.prototype.slice.call(arguments);
                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                if (arguments.callee['im_self'] !== null) {
                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                }
                            }
                            var a = @{{_getattr}}(arguments.callee, '__call__');
                            if (typeof a == "undefined") {
                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                            }
                            if (args.length >= 3) {
                                var len = args.length;
                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                            }
                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                        _new_dst$['toString'] = function ( ) {
                            try {
                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                            } catch (e) {
                            }
                            try {
                                return "<" + this.__class__.__name__ + " instance>";
                            } catch (e) {
                            }
                            return "<instance>";
                        };
                        _new_dst$['$inst'] = true;
                        if (typeof @{{instancemethod}} == "undefined") {
                            debugger;
                        }
                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                            _new_dst$['__dict__'] = B$dict();
                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                        }
                        _new_dst$['__class__'] = @{{instancemethod}};
                        _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                        _new_dst$['im_func'] = meth;
                        _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                        meth = _new_dst$;
                        break;
                    case @{{staticmethod}}:
                        meth = meth['im_func'];
                        break;
                    case @{{classmethod}}:
                        var _new_dst$ = function ( ) {
                            var args = Array.prototype.slice.call(arguments);
                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                if (arguments.callee['im_self'] !== null) {
                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                }
                            }
                            var a = @{{_getattr}}(arguments.callee, '__call__');
                            if (typeof a == "undefined") {
                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                            }
                            if (args.length >= 3) {
                                var len = args.length;
                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                            }
                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                        _new_dst$['toString'] = function ( ) {
                            try {
                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                            } catch (e) {
                            }
                            try {
                                return "<" + this.__class__.__name__ + " instance>";
                            } catch (e) {
                            }
                            return "<instance>";
                        };
                        _new_dst$['$inst'] = true;
                        if (typeof @{{instancemethod}} == "undefined") {
                            debugger;
                        }
                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                            _new_dst$['__dict__'] = B$dict();
                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                        }
                        _new_dst$['__class__'] = @{{instancemethod}};
                        _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                        _new_dst$['im_func'] = meth['im_func'];
                        _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                        meth = _new_dst$;
                        break;
                    case @{{bool}}: // Some known to be non-descriptors
                    case @{{int}}:
                    case @{{long}}:
                    case @{{str}}:
                        break;
                    default:
                        // check for __get__ method in meth
                        if (meth['$inst'] === true) {
                            var get$ = @{{_getattr}}(meth, '__get__');
                            if (typeof get$ != 'undefined') {
                                meth = @{{fcall}}(this, null, get$, meth, $obj, $obj['__class__']);
                            }
                        }
                        break;
                }
            }
            if (attr == '__setslice__') {
                var start = $slice[0] === N$ ? @{{int_zero}} : $slice[0],
                    stop = $slice[1] === N$ ? @{{int_max_index}} : $slice[1];
                return @{{fcall}}(this, null, meth, $obj, start, stop, $value);
            }
            $slice = $new.apply(null, [@{{slice}}].concat($slice));
            return @{{fcall}}(null, null, meth, $obj, $slice, $value);
        }
    }
    if (typeof $obj['$inst'] != "undefined") {
        return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof($obj) + "' object does not support item assignment")));
    }
    return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof($obj) + "' does not support slice assignment")));
});

func(m$, null, g$, 'delitem', 1, ['obj', 'name'], null, null, null, function($obj, $name) {
    var meth;
    meth = [][1];
    var mro$ = $obj['__mro__'];
    var _meth_src = $obj;
    switch ($obj['$inst']) {
        case true:
            if ($obj['__class__'] === @{{module}}) {
                meth = $obj['$dict']['__delitem__'];
                break;
            } else if ($obj['__class__'] === @{{function}}) {
                switch ('__delitem__'.charAt(0)) {
                    case 'i':
                    case '_':
                        meth = $obj['__delitem__'];
                }
                break;
            }
            var _noraise$ = @{{noraise}};
            var ga;
            mro$ = $obj['__class__']['__mro__'];
            for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                var _mro$ = mro$[mro_i$];
                var ga = _mro$['__getattribute__'];
                if (typeof ga == "undefined") {
                    if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                        continue;
                    }
                    ga = _mro$['$dict']['__getattribute__'];
                }
                if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                    switch (ga['__class__']) {
                        case @{{function}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            _new_dst$['im_func'] = ga;
                            _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                            ga = _new_dst$;
                            break;
                        case @{{staticmethod}}:
                            ga = ga['im_func'];
                            break;
                        case @{{classmethod}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            _new_dst$['im_func'] = ga['im_func'];
                            _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            ga = _new_dst$;
                            break;
                        case @{{bool}}: // Some known to be non-descriptors
                        case @{{int}}:
                        case @{{long}}:
                        case @{{str}}:
                            break;
                        default:
                            // check for __get__ method in ga
                            if (ga['$inst'] === true) {
                                var get$ = @{{_getattr}}(ga, '__get__');
                                if (typeof get$ != 'undefined') {
                                    ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                }
                            }
                            break;
                    }
                }
                @{{noraise}} = @{{AttributeError}};
                meth = @{{fcall}}(this, null, ga, _mro$, '__delitem__');
                @{{noraise}} = _noraise$;
                if (meth === @{{AttributeError}}) {
                    meth = [][1];
                }
                _meth_src = $obj['__class__'];
                $obj = $obj['__class__'];
                break;
            }
            if (typeof meth == "undefined") {
                if (typeof $obj['$dict'] != "undefined") {
                    meth = $obj['$dict']['__delitem__'];
                    if (typeof meth != "undefined") {
                        if (meth !== {}['__delitem__']) {
                            break;
                        }
                        meth = [][1];
                    }
                }
                switch ('__delitem__'.charAt(0)) {
                    case 'i':
                    case '_':
                        meth = $obj['__delitem__'];
                }
                if (typeof meth != "undefined") {
                    break;
                }
            }
        case false:
            if (typeof meth == "undefined") {
                var _mro$, ga;
                if ($obj['$inst'] === true) {
                    _meth_src = $obj['__class__'];
                } else {
                    switch ('__delitem__'.charAt(0)) {
                        case 'i':
                        case '_':
                            meth = $obj['__delitem__'];
                    }
                    if (typeof meth != "undefined") {
                        break;
                    }

                }
                if (typeof meth == "undefined") {
                    for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        meth = _mro$['$dict']['__delitem__'];
                        if (typeof meth != "undefined") {
                            if (meth !== {}['__delitem__']) {
                                break;
                            }
                            meth = [][1];
                        }
                        switch ('__delitem__'.charAt(0)) {
                            case 'i':
                            case '_':
                                meth = _mro$['__delitem__'];
                        }
                        if (typeof meth != "undefined") {
                            break;
                        }
                    }
                }
                if (typeof meth == "undefined" && '__delitem__' !== '__get__') {
                    for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattr__'];
                        if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                            switch (ga['__class__']) {
                                case @{{function}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    _new_dst$['im_func'] = ga;
                                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                                    ga = _new_dst$;
                                    break;
                                case @{{staticmethod}}:
                                    ga = ga['im_func'];
                                    break;
                                case @{{classmethod}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    _new_dst$['im_func'] = ga['im_func'];
                                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    ga = _new_dst$;
                                    break;
                                case @{{bool}}: // Some known to be non-descriptors
                                case @{{int}}:
                                case @{{long}}:
                                case @{{str}}:
                                    break;
                                default:
                                    // check for __get__ method in ga
                                    if (ga['$inst'] === true) {
                                        var get$ = @{{_getattr}}(ga, '__get__');
                                        if (typeof get$ != 'undefined') {
                                            ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                        }
                                    }
                                    break;
                            }
                        }
                        @{{noraise}} = @{{AttributeError}};
                        meth = @{{fcall}}(this, null, ga, _mro$, '__delitem__');
                        @{{noraise}} = _noraise$;
                        if (meth === @{{AttributeError}}) {
                            meth = [][1];
                        }
                        // TODO : unbind meth ?
                        break;
                    }
                }
            }
            break;
        default:
            meth = $obj['__delitem__'];
            if (typeof meth == "undefined" && typeof $obj['$dict'] != "undefined") {
                meth = $obj['$dict']['__delitem__'];
            }
    }
    if (typeof meth != "undefined") {
        if (_meth_src['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof meth != "undefined" && typeof meth['$inst'] != "undefined") {
            switch (meth['__class__']) {
                case @{{function}}:
                    var _new_dst$ = function ( ) {
                        var args = Array.prototype.slice.call(arguments);
                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                            if (arguments.callee['im_self'] !== null) {
                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                            }
                        }
                        var a = @{{_getattr}}(arguments.callee, '__call__');
                        if (typeof a == "undefined") {
                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                        }
                        if (args.length >= 3) {
                            var len = args.length;
                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                        }
                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                    }
                    _new_dst$['toString'] = function ( ) {
                        try {
                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                        } catch (e) {
                        }
                        try {
                            return "<" + this.__class__.__name__ + " instance>";
                        } catch (e) {
                        }
                        return "<instance>";
                    };
                    _new_dst$['$inst'] = true;
                    if (typeof @{{instancemethod}} == "undefined") {
                        debugger;
                    }
                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                        _new_dst$['__dict__'] = B$dict();
                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                    }
                    _new_dst$['__class__'] = @{{instancemethod}};
                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                    _new_dst$['im_func'] = meth;
                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                    meth = _new_dst$;
                    break;
                case @{{staticmethod}}:
                    meth = meth['im_func'];
                    break;
                case @{{classmethod}}:
                    var _new_dst$ = function ( ) {
                        var args = Array.prototype.slice.call(arguments);
                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                            if (arguments.callee['im_self'] !== null) {
                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                            }
                        }
                        var a = @{{_getattr}}(arguments.callee, '__call__');
                        if (typeof a == "undefined") {
                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                        }
                        if (args.length >= 3) {
                            var len = args.length;
                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                        }
                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                    }
                    _new_dst$['toString'] = function ( ) {
                        try {
                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                        } catch (e) {
                        }
                        try {
                            return "<" + this.__class__.__name__ + " instance>";
                        } catch (e) {
                        }
                        return "<instance>";
                    };
                    _new_dst$['$inst'] = true;
                    if (typeof @{{instancemethod}} == "undefined") {
                        debugger;
                    }
                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                        _new_dst$['__dict__'] = B$dict();
                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                    }
                    _new_dst$['__class__'] = @{{instancemethod}};
                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                    _new_dst$['im_func'] = meth['im_func'];
                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                    meth = _new_dst$;
                    break;
                case @{{bool}}: // Some known to be non-descriptors
                case @{{int}}:
                case @{{long}}:
                case @{{str}}:
                    break;
                default:
                    // check for __get__ method in meth
                    if (meth['$inst'] === true) {
                        var get$ = @{{_getattr}}(meth, '__get__');
                        if (typeof get$ != 'undefined') {
                            meth = @{{fcall}}(this, null, get$, meth, $obj, $obj['__class__']);
                        }
                    }
                    break;
            }
        }
        return @{{fcall}}(this, null, meth, $obj, $name);
    }
    if (typeof $obj['$inst'] != "undefined") {
        return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof($obj) + "' object does not support item deletion")));
    }
    if (typeof $obj instanceof Array) {
        var idx = $name.valueOf();
        if (typeof idx == 'number') {
            // TODO: determine if a Array.splice is needed
            delete $obj[idx];
            return N$
        }
        return @{{raise}}($new(@{{TypeError}}, B$str("Javascript array needs number indexes not '" + _typeof($name) + "'")));
    }
    if (typeof $obj == 'object') {
        var name = $name.valueOf();
        if (typeof name == 'string') {
            delete $obj[name];
        } else {
            delete $obj[$name];
        }
        return N$
    }
    return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof($obj) + "' does not support item deletion")));
});

func(m$, null, g$, 'delslice', 1, ['obj', 'name'], null, null, null, function($obj, $slice) {
    var meth, attrs = $slice.length == 2 ? ['__delslice__', '__delitem__'] : ['__delitem__'];
    for (var attri = 0 ; attri < attrs.length; attri++) {
        var attr = attrs[attri];
        meth = [][1];
        var mro$ = $obj['__mro__'];
        var _meth_src = $obj;
        switch ($obj['$inst']) {
            case true:
                if ($obj['__class__'] === @{{module}}) {
                    meth = $obj['$dict'][attr];
                    break;
                } else if ($obj['__class__'] === @{{function}}) {
                    switch (attr.charAt(0)) {
                        case 'i':
                        case '_':
                            meth = $obj[attr];
                    }
                    break;
                }
                var _noraise$ = @{{noraise}};
                var ga;
                mro$ = $obj['__class__']['__mro__'];
                for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                    var _mro$ = mro$[mro_i$];
                    var ga = _mro$['__getattribute__'];
                    if (typeof ga == "undefined") {
                        if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattribute__'];
                    }
                    if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                        switch (ga['__class__']) {
                            case @{{function}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                _new_dst$['im_func'] = ga;
                                _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                                ga = _new_dst$;
                                break;
                            case @{{staticmethod}}:
                                ga = ga['im_func'];
                                break;
                            case @{{classmethod}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                _new_dst$['im_func'] = ga['im_func'];
                                _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                ga = _new_dst$;
                                break;
                            case @{{bool}}: // Some known to be non-descriptors
                            case @{{int}}:
                            case @{{long}}:
                            case @{{str}}:
                                break;
                            default:
                                // check for __get__ method in ga
                                if (ga['$inst'] === true) {
                                    var get$ = @{{_getattr}}(ga, '__get__');
                                    if (typeof get$ != 'undefined') {
                                        ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                    }
                                }
                                break;
                        }
                    }
                    @{{noraise}} = @{{AttributeError}};
                    meth = @{{fcall}}(this, null, ga, _mro$, attr);
                    @{{noraise}} = _noraise$;
                    if (meth === @{{AttributeError}}) {
                        meth = [][1];
                    }
                    _meth_src = $obj['__class__'];
                    $obj = $obj['__class__'];
                    break;
                }
                if (typeof meth == "undefined") {
                    if (typeof $obj['$dict'] != "undefined") {
                        meth = $obj['$dict'][attr];
                        if (typeof meth != "undefined") {
                            if (meth !== {}[attr]) {
                                break;
                            }
                            meth = [][1];
                        }
                    }
                    switch (attr.charAt(0)) {
                        case 'i':
                        case '_':
                            meth = $obj[attr];
                    }
                    if (typeof meth != "undefined") {
                        break;
                    }
                }
            case false:
                if (typeof meth == "undefined") {
                    var _mro$, ga;
                    if ($obj['$inst'] === true) {
                        _meth_src = $obj['__class__'];
                    } else {
                        switch (attr.charAt(0)) {
                            case 'i':
                            case '_':
                                meth = $obj[attr];
                        }
                        if (typeof meth != "undefined") {
                            break;
                        }

                    }
                    if (typeof meth == "undefined") {
                        for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            meth = _mro$['$dict'][attr];
                            if (typeof meth != "undefined") {
                                if (meth !== {}[attr]) {
                                    break;
                                }
                                meth = [][1];
                            }
                            switch (attr.charAt(0)) {
                                case 'i':
                                case '_':
                                    meth = _mro$[attr];
                            }
                            if (typeof meth != "undefined") {
                                break;
                            }
                        }
                    }
                    if (typeof meth == "undefined" && attr !== '__get__') {
                        for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                continue;
                            }
                            ga = _mro$['$dict']['__getattr__'];
                            if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                                switch (ga['__class__']) {
                                    case @{{function}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                        _new_dst$['im_func'] = ga;
                                        _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                                        ga = _new_dst$;
                                        break;
                                    case @{{staticmethod}}:
                                        ga = ga['im_func'];
                                        break;
                                    case @{{classmethod}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                        _new_dst$['im_func'] = ga['im_func'];
                                        _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                        ga = _new_dst$;
                                        break;
                                    case @{{bool}}: // Some known to be non-descriptors
                                    case @{{int}}:
                                    case @{{long}}:
                                    case @{{str}}:
                                        break;
                                    default:
                                        // check for __get__ method in ga
                                        if (ga['$inst'] === true) {
                                            var get$ = @{{_getattr}}(ga, '__get__');
                                            if (typeof get$ != 'undefined') {
                                                ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                            }
                                        }
                                        break;
                                }
                            }
                            @{{noraise}} = @{{AttributeError}};
                            meth = @{{fcall}}(this, null, ga, _mro$, attr);
                            @{{noraise}} = _noraise$;
                            if (meth === @{{AttributeError}}) {
                                meth = [][1];
                            }
                            // TODO : unbind meth ?
                            break;
                        }
                    }
                }
                break;
            default:
                meth = $obj[attr];
                if (typeof meth == "undefined" && typeof $obj['$dict'] != "undefined") {
                    meth = $obj['$dict'][attr];
                }
        }
        if (typeof meth != "undefined") {
            if (_meth_src['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof meth != "undefined" && typeof meth['$inst'] != "undefined") {
                switch (meth['__class__']) {
                    case @{{function}}:
                        var _new_dst$ = function ( ) {
                            var args = Array.prototype.slice.call(arguments);
                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                if (arguments.callee['im_self'] !== null) {
                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                }
                            }
                            var a = @{{_getattr}}(arguments.callee, '__call__');
                            if (typeof a == "undefined") {
                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                            }
                            if (args.length >= 3) {
                                var len = args.length;
                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                            }
                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                        _new_dst$['toString'] = function ( ) {
                            try {
                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                            } catch (e) {
                            }
                            try {
                                return "<" + this.__class__.__name__ + " instance>";
                            } catch (e) {
                            }
                            return "<instance>";
                        };
                        _new_dst$['$inst'] = true;
                        if (typeof @{{instancemethod}} == "undefined") {
                            debugger;
                        }
                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                            _new_dst$['__dict__'] = B$dict();
                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                        }
                        _new_dst$['__class__'] = @{{instancemethod}};
                        _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                        _new_dst$['im_func'] = meth;
                        _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                        meth = _new_dst$;
                        break;
                    case @{{staticmethod}}:
                        meth = meth['im_func'];
                        break;
                    case @{{classmethod}}:
                        var _new_dst$ = function ( ) {
                            var args = Array.prototype.slice.call(arguments);
                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                if (arguments.callee['im_self'] !== null) {
                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                }
                            }
                            var a = @{{_getattr}}(arguments.callee, '__call__');
                            if (typeof a == "undefined") {
                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                            }
                            if (args.length >= 3) {
                                var len = args.length;
                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                            }
                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                        _new_dst$['toString'] = function ( ) {
                            try {
                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                            } catch (e) {
                            }
                            try {
                                return "<" + this.__class__.__name__ + " instance>";
                            } catch (e) {
                            }
                            return "<instance>";
                        };
                        _new_dst$['$inst'] = true;
                        if (typeof @{{instancemethod}} == "undefined") {
                            debugger;
                        }
                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                            _new_dst$['__dict__'] = B$dict();
                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                        }
                        _new_dst$['__class__'] = @{{instancemethod}};
                        _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                        _new_dst$['im_func'] = meth['im_func'];
                        _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                        meth = _new_dst$;
                        break;
                    case @{{bool}}: // Some known to be non-descriptors
                    case @{{int}}:
                    case @{{long}}:
                    case @{{str}}:
                        break;
                    default:
                        // check for __get__ method in meth
                        if (meth['$inst'] === true) {
                            var get$ = @{{_getattr}}(meth, '__get__');
                            if (typeof get$ != 'undefined') {
                                meth = @{{fcall}}(this, null, get$, meth, $obj, $obj['__class__']);
                            }
                        }
                        break;
                }
            }
            if (attr == '__delslice__') {
                var start = $slice[0] === N$ ? @{{int_zero}} : $slice[0],
                    stop = $slice[1] === N$ ? @{{int_max_index}} : $slice[1];
                return @{{fcall}}(this, null, meth, $obj, start, stop);
            }
            $slice = $new.apply(null, [@{{slice}}].concat($slice));
            return @{{fcall}}(null, null, meth, $obj, $slice);
        }
    }
    if (typeof $obj['$inst'] != "undefined") {
        return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof($obj) + "' object does not support item deletion")));
    }
    return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof($obj) + "' does not support slice deletion")));
});

func(m$, null, g$, 'getitem', 1, ['obj', 'name'], null, null, null, function($obj, $name) {
    var meth;
    meth = [][1];
    var mro$ = $obj['__mro__'];
    var _meth_src = $obj;
    switch ($obj['$inst']) {
        case true:
            if ($obj['__class__'] === @{{module}}) {
                meth = $obj['$dict']['__getitem__'];
                break;
            } else if ($obj['__class__'] === @{{function}}) {
                switch ('__getitem__'.charAt(0)) {
                    case 'i':
                    case '_':
                        meth = $obj['__getitem__'];
                }
                break;
            }
            var _noraise$ = @{{noraise}};
            var ga;
            mro$ = $obj['__class__']['__mro__'];
            for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                var _mro$ = mro$[mro_i$];
                var ga = _mro$['__getattribute__'];
                if (typeof ga == "undefined") {
                    if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                        continue;
                    }
                    ga = _mro$['$dict']['__getattribute__'];
                }
                if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                    switch (ga['__class__']) {
                        case @{{function}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            _new_dst$['im_func'] = ga;
                            _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                            ga = _new_dst$;
                            break;
                        case @{{staticmethod}}:
                            ga = ga['im_func'];
                            break;
                        case @{{classmethod}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            _new_dst$['im_func'] = ga['im_func'];
                            _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                            ga = _new_dst$;
                            break;
                        case @{{bool}}: // Some known to be non-descriptors
                        case @{{int}}:
                        case @{{long}}:
                        case @{{str}}:
                            break;
                        default:
                            // check for __get__ method in ga
                            if (ga['$inst'] === true) {
                                var get$ = @{{_getattr}}(ga, '__get__');
                                if (typeof get$ != 'undefined') {
                                    ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                }
                            }
                            break;
                    }
                }
                @{{noraise}} = @{{AttributeError}};
                meth = @{{fcall}}(this, null, ga, _mro$, '__getitem__');
                @{{noraise}} = _noraise$;
                if (meth === @{{AttributeError}}) {
                    meth = [][1];
                }
                _meth_src = $obj['__class__'];
                $obj = $obj['__class__'];
                break;
            }
            if (typeof meth == "undefined") {
                if (typeof $obj['$dict'] != "undefined") {
                    meth = $obj['$dict']['__getitem__'];
                    if (typeof meth != "undefined") {
                        if (meth !== {}['__getitem__']) {
                            break;
                        }
                        meth = [][1];
                    }
                }
                switch ('__getitem__'.charAt(0)) {
                    case 'i':
                    case '_':
                        meth = $obj['__getitem__'];
                }
                if (typeof meth != "undefined") {
                    break;
                }
            }
        case false:
            if (typeof meth == "undefined") {
                var _mro$, ga;
                if ($obj['$inst'] === true) {
                    _meth_src = $obj['__class__'];
                } else {
                    switch ('__getitem__'.charAt(0)) {
                        case 'i':
                        case '_':
                            meth = $obj['__getitem__'];
                    }
                    if (typeof meth != "undefined") {
                        break;
                    }

                }
                if (typeof meth == "undefined") {
                    for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        meth = _mro$['$dict']['__getitem__'];
                        if (typeof meth != "undefined") {
                            if (meth !== {}['__getitem__']) {
                                break;
                            }
                            meth = [][1];
                        }
                        switch ('__getitem__'.charAt(0)) {
                            case 'i':
                            case '_':
                                meth = _mro$['__getitem__'];
                        }
                        if (typeof meth != "undefined") {
                            break;
                        }
                    }
                }
                if (typeof meth == "undefined" && '__getitem__' !== '__get__') {
                    for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattr__'];
                        if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                            switch (ga['__class__']) {
                                case @{{function}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    _new_dst$['im_func'] = ga;
                                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                                    ga = _new_dst$;
                                    break;
                                case @{{staticmethod}}:
                                    ga = ga['im_func'];
                                    break;
                                case @{{classmethod}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    _new_dst$['im_func'] = ga['im_func'];
                                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                    ga = _new_dst$;
                                    break;
                                case @{{bool}}: // Some known to be non-descriptors
                                case @{{int}}:
                                case @{{long}}:
                                case @{{str}}:
                                    break;
                                default:
                                    // check for __get__ method in ga
                                    if (ga['$inst'] === true) {
                                        var get$ = @{{_getattr}}(ga, '__get__');
                                        if (typeof get$ != 'undefined') {
                                            ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                        }
                                    }
                                    break;
                            }
                        }
                        @{{noraise}} = @{{AttributeError}};
                        meth = @{{fcall}}(this, null, ga, _mro$, '__getitem__');
                        @{{noraise}} = _noraise$;
                        if (meth === @{{AttributeError}}) {
                            meth = [][1];
                        }
                        // TODO : unbind meth ?
                        break;
                    }
                }
            }
            break;
        default:
            meth = $obj['__getitem__'];
            if (typeof meth == "undefined" && typeof $obj['$dict'] != "undefined") {
                meth = $obj['$dict']['__getitem__'];
            }
    }
    if (typeof meth != "undefined") {
        if (_meth_src['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof meth != "undefined" && typeof meth['$inst'] != "undefined") {
            switch (meth['__class__']) {
                case @{{function}}:
                    var _new_dst$ = function ( ) {
                        var args = Array.prototype.slice.call(arguments);
                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                            if (arguments.callee['im_self'] !== null) {
                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                            }
                        }
                        var a = @{{_getattr}}(arguments.callee, '__call__');
                        if (typeof a == "undefined") {
                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                        }
                        if (args.length >= 3) {
                            var len = args.length;
                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                        }
                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                    }
                    _new_dst$['toString'] = function ( ) {
                        try {
                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                        } catch (e) {
                        }
                        try {
                            return "<" + this.__class__.__name__ + " instance>";
                        } catch (e) {
                        }
                        return "<instance>";
                    };
                    _new_dst$['$inst'] = true;
                    if (typeof @{{instancemethod}} == "undefined") {
                        debugger;
                    }
                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                        _new_dst$['__dict__'] = B$dict();
                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                    }
                    _new_dst$['__class__'] = @{{instancemethod}};
                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                    _new_dst$['im_func'] = meth;
                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                    meth = _new_dst$;
                    break;
                case @{{staticmethod}}:
                    meth = meth['im_func'];
                    break;
                case @{{classmethod}}:
                    var _new_dst$ = function ( ) {
                        var args = Array.prototype.slice.call(arguments);
                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                            if (arguments.callee['im_self'] !== null) {
                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                            }
                        }
                        var a = @{{_getattr}}(arguments.callee, '__call__');
                        if (typeof a == "undefined") {
                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                        }
                        if (args.length >= 3) {
                            var len = args.length;
                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                        }
                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                    }
                    _new_dst$['toString'] = function ( ) {
                        try {
                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                        } catch (e) {
                        }
                        try {
                            return "<" + this.__class__.__name__ + " instance>";
                        } catch (e) {
                        }
                        return "<instance>";
                    };
                    _new_dst$['$inst'] = true;
                    if (typeof @{{instancemethod}} == "undefined") {
                        debugger;
                    }
                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                        _new_dst$['__dict__'] = B$dict();
                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                    }
                    _new_dst$['__class__'] = @{{instancemethod}};
                    _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                    _new_dst$['im_func'] = meth['im_func'];
                    _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                    meth = _new_dst$;
                    break;
                case @{{bool}}: // Some known to be non-descriptors
                case @{{int}}:
                case @{{long}}:
                case @{{str}}:
                    break;
                default:
                    // check for __get__ method in meth
                    if (meth['$inst'] === true) {
                        var get$ = @{{_getattr}}(meth, '__get__');
                        if (typeof get$ != 'undefined') {
                            meth = @{{fcall}}(this, null, get$, meth, $obj, $obj['__class__']);
                        }
                    }
                    break;
            }
        }
        return @{{fcall}}(this, null, meth, $obj, $name);
    }
    if (typeof $obj['$inst'] != "undefined") {
        return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof($obj) + "' object is unsubscriptable")));
    }
    if (typeof $obj instanceof Array) {
        var idx = $name.valueOf();
        if (typeof idx == 'number') {
            return $obj[idx];
        }
        return @{{raise}}($new(@{{TypeError}}, B$str("Javascript array needs number indexes not '" + _typeof($name) + "'")));
    }
    if (typeof $obj == 'object') {
        var name = $name.valueOf();
        if (typeof name == 'string') {
            return $obj[name];
        } else {
            return $obj[$name];
        }
        return N$
    }
    return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof($obj) +"' is unsubscriptable")));
});

func(m$, null, g$, 'getslice', 1, ['obj', 'name'], null, null, null, function($obj, $slice) {
    var meth, attrs = $slice.length == 2 ? ['__getslice__', '__getitem__'] : ['__getitem__'];
    for (var attri = 0 ; attri < attrs.length; attri++) {
        var attr = attrs[attri];
        meth = [][1];
        var mro$ = $obj['__mro__'];
        var _meth_src = $obj;
        switch ($obj['$inst']) {
            case true:
                if ($obj['__class__'] === @{{module}}) {
                    meth = $obj['$dict'][attr];
                    break;
                } else if ($obj['__class__'] === @{{function}}) {
                    switch (attr.charAt(0)) {
                        case 'i':
                        case '_':
                            meth = $obj[attr];
                    }
                    break;
                }
                var _noraise$ = @{{noraise}};
                var ga;
                mro$ = $obj['__class__']['__mro__'];
                for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                    var _mro$ = mro$[mro_i$];
                    var ga = _mro$['__getattribute__'];
                    if (typeof ga == "undefined") {
                        if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattribute__'];
                    }
                    if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                        switch (ga['__class__']) {
                            case @{{function}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                _new_dst$['im_func'] = ga;
                                _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                                ga = _new_dst$;
                                break;
                            case @{{staticmethod}}:
                                ga = ga['im_func'];
                                break;
                            case @{{classmethod}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                _new_dst$['im_func'] = ga['im_func'];
                                _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                ga = _new_dst$;
                                break;
                            case @{{bool}}: // Some known to be non-descriptors
                            case @{{int}}:
                            case @{{long}}:
                            case @{{str}}:
                                break;
                            default:
                                // check for __get__ method in ga
                                if (ga['$inst'] === true) {
                                    var get$ = @{{_getattr}}(ga, '__get__');
                                    if (typeof get$ != 'undefined') {
                                        ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                    }
                                }
                                break;
                        }
                    }
                    @{{noraise}} = @{{AttributeError}};
                    meth = @{{fcall}}(this, null, ga, _mro$, attr);
                    @{{noraise}} = _noraise$;
                    if (meth === @{{AttributeError}}) {
                        meth = [][1];
                    }
                    _meth_src = $obj['__class__'];
                    $obj = $obj['__class__'];
                    break;
                }
                if (typeof meth == "undefined") {
                    if (typeof $obj['$dict'] != "undefined") {
                        meth = $obj['$dict'][attr];
                        if (typeof meth != "undefined") {
                            if (meth !== {}[attr]) {
                                break;
                            }
                            meth = [][1];
                        }
                    }
                    switch (attr.charAt(0)) {
                        case 'i':
                        case '_':
                            meth = $obj[attr];
                    }
                    if (typeof meth != "undefined") {
                        break;
                    }
                }
            case false:
                if (typeof meth == "undefined") {
                    var _mro$, ga;
                    if ($obj['$inst'] === true) {
                        _meth_src = $obj['__class__'];
                    } else {
                        switch (attr.charAt(0)) {
                            case 'i':
                            case '_':
                                meth = $obj[attr];
                        }
                        if (typeof meth != "undefined") {
                            break;
                        }

                    }
                    if (typeof meth == "undefined") {
                        for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            meth = _mro$['$dict'][attr];
                            if (typeof meth != "undefined") {
                                if (meth !== {}[attr]) {
                                    break;
                                }
                                meth = [][1];
                            }
                            switch (attr.charAt(0)) {
                                case 'i':
                                case '_':
                                    meth = _mro$[attr];
                            }
                            if (typeof meth != "undefined") {
                                break;
                            }
                        }
                    }
                    if (typeof meth == "undefined" && attr !== '__get__') {
                        for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                continue;
                            }
                            ga = _mro$['$dict']['__getattr__'];
                            if ($obj['__class__']['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof $obj != "undefined" && typeof $obj['$inst'] != "undefined") {
                                switch (ga['__class__']) {
                                    case @{{function}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                        _new_dst$['im_func'] = ga;
                                        _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                                        ga = _new_dst$;
                                        break;
                                    case @{{staticmethod}}:
                                        ga = ga['im_func'];
                                        break;
                                    case @{{classmethod}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                        _new_dst$['im_func'] = ga['im_func'];
                                        _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                                        ga = _new_dst$;
                                        break;
                                    case @{{bool}}: // Some known to be non-descriptors
                                    case @{{int}}:
                                    case @{{long}}:
                                    case @{{str}}:
                                        break;
                                    default:
                                        // check for __get__ method in ga
                                        if (ga['$inst'] === true) {
                                            var get$ = @{{_getattr}}(ga, '__get__');
                                            if (typeof get$ != 'undefined') {
                                                ga = @{{fcall}}(this, null, get$, ga, $obj, $obj['__class__']);
                                            }
                                        }
                                        break;
                                }
                            }
                            @{{noraise}} = @{{AttributeError}};
                            meth = @{{fcall}}(this, null, ga, _mro$, attr);
                            @{{noraise}} = _noraise$;
                            if (meth === @{{AttributeError}}) {
                                meth = [][1];
                            }
                            // TODO : unbind meth ?
                            break;
                        }
                    }
                }
                break;
            default:
                meth = $obj[attr];
                if (typeof meth == "undefined" && typeof $obj['$dict'] != "undefined") {
                    meth = $obj['$dict'][attr];
                }
        }
        if (typeof meth != "undefined") {
            if (_meth_src['$inst'] === false && $obj['__class__'] !== @{{module}} && typeof meth != "undefined" && typeof meth['$inst'] != "undefined") {
                switch (meth['__class__']) {
                    case @{{function}}:
                        var _new_dst$ = function ( ) {
                            var args = Array.prototype.slice.call(arguments);
                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                if (arguments.callee['im_self'] !== null) {
                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                }
                            }
                            var a = @{{_getattr}}(arguments.callee, '__call__');
                            if (typeof a == "undefined") {
                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                            }
                            if (args.length >= 3) {
                                var len = args.length;
                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                            }
                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                        _new_dst$['toString'] = function ( ) {
                            try {
                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                            } catch (e) {
                            }
                            try {
                                return "<" + this.__class__.__name__ + " instance>";
                            } catch (e) {
                            }
                            return "<instance>";
                        };
                        _new_dst$['$inst'] = true;
                        if (typeof @{{instancemethod}} == "undefined") {
                            debugger;
                        }
                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                            _new_dst$['__dict__'] = B$dict();
                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                        }
                        _new_dst$['__class__'] = @{{instancemethod}};
                        _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                        _new_dst$['im_func'] = meth;
                        _new_dst$['im_self'] = $obj['$inst'] === true ? $obj : null;
                        meth = _new_dst$;
                        break;
                    case @{{staticmethod}}:
                        meth = meth['im_func'];
                        break;
                    case @{{classmethod}}:
                        var _new_dst$ = function ( ) {
                            var args = Array.prototype.slice.call(arguments);
                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                if (arguments.callee['im_self'] !== null) {
                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                }
                            }
                            var a = @{{_getattr}}(arguments.callee, '__call__');
                            if (typeof a == "undefined") {
                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                            }
                            if (args.length >= 3) {
                                var len = args.length;
                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                            }
                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                        _new_dst$['toString'] = function ( ) {
                            try {
                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                            } catch (e) {
                            }
                            try {
                                return "<" + this.__class__.__name__ + " instance>";
                            } catch (e) {
                            }
                            return "<instance>";
                        };
                        _new_dst$['$inst'] = true;
                        if (typeof @{{instancemethod}} == "undefined") {
                            debugger;
                        }
                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                            _new_dst$['__dict__'] = B$dict();
                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                        }
                        _new_dst$['__class__'] = @{{instancemethod}};
                        _new_dst$['im_class'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                        _new_dst$['im_func'] = meth['im_func'];
                        _new_dst$['im_self'] = $obj['$inst'] === true ? $obj['__class__'] : $obj;
                        meth = _new_dst$;
                        break;
                    case @{{bool}}: // Some known to be non-descriptors
                    case @{{int}}:
                    case @{{long}}:
                    case @{{str}}:
                        break;
                    default:
                        // check for __get__ method in meth
                        if (meth['$inst'] === true) {
                            var get$ = @{{_getattr}}(meth, '__get__');
                            if (typeof get$ != 'undefined') {
                                meth = @{{fcall}}(this, null, get$, meth, $obj, $obj['__class__']);
                            }
                        }
                        break;
                }
            }
            if (attr == '__getslice__') {
                var start = $slice[0] === N$ ? @{{int_zero}} : $slice[0],
                    stop = $slice[1] === N$ ? @{{int_max_index}} : $slice[1];
                return @{{fcall}}(this, null, meth, $obj, start, stop);
            }
            $slice = $new.apply(null, [@{{slice}}].concat($slice));
            return @{{fcall}}(null, null, meth, $obj, $slice);
        }
    }
    if (typeof $obj['$inst'] != "undefined") {
        return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof($obj) + "' object is unsubscriptable")));
    }
    return @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof($obj) +"' does not support slices")));
});

@{{type}} = type(m$, 'type', [@{{object}}], {}, []);
func(m$, null, @{{type}}, '__new__', 0, ['cls', 'clsname', 'bases', 'dict'], null, null, [null, null], function($cls, $clsname, $bases, $dict) {
    var narg = arguments.length;
    while (arguments[--narg] === null);
    if (narg == 3) {
        var cls,
            mro$ = new Array(),
            _bases = $bases;
            cls = function () {
                var args = Array.prototype.slice.call(arguments);
                if (args.length >= 3) {
                    var len = args.length;
                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                        return $newext.apply(this, [arguments.callee].concat(args));
                    }
                }
                return $new.apply(this, [arguments.callee].concat(args));
        };
        cls['$inst'] = false;
        cls['__name__'] = typeof $clsname == "string" ? B$str($clsname) : $clsname;
        if ($bases instanceof Array) {
            cls['__bases__'] = B$tuple($bases);
        } else {
            cls['__bases__'] = $bases;
            _bases = $bases['__array'];
        }
        if (typeof $dict['mro'] != "undefined") {
            // The mro method (?) exists. Use that.
            // TODO
            @{{raise}}(@{{NotImplemented}});
        } else {
            for (var i = 0; i < _bases.length; i++) {
                mro$.push(new Array().concat(_bases[i].__mro__));
            }
            cls['__mro__'] = [cls].concat(mro_merge(mro$));
        }
        cls['$dict'] = {};
        if (this['__class__'] !== @{{module}}) {
            debugger;
        }
        var __module__ = typeof this['$dict'] != "undefined" ? this['$dict']['__name__'] : this['__name__'];
        if (typeof __module__ != "undefined") {
            cls['$dict']['__module__'] = __module__;
        }
        if (typeof $dict != "undefined" && $dict['__class__'] === @{{dict}}) {
            for (var k in $dict.__object) {
                cls['$dict'][k] = $dict.__object[k];
            }
        }
        cls['__dict__'] = @{{dictproxy}};
        cls['__dict__']['__object'] = cls['$dict'];
        func(m$, null, cls, '__call__', 3, null, 'args', 'kwargs', null, $newext, true);
        cls['__class__'] = @{{type}};
        cls.toString = function () { return "<class " + $clsname + ">";};
        return cls;
    }
    if (narg == 1) {
        return $clsname['__class__'];
    }
    @{{raise}}($new(@{{TypeError}}, B$str("type() takes 1 or 3 arguments")));
});



@{{object}}['__bases__'] = B$tuple(@{{object}}['__bases__']);
@{{tuple}}['__bases__'] = B$tuple(@{{tuple}}['__bases__']);
@{{dictproxy}}['__bases__'] = B$tuple(@{{dictproxy}}['__bases__']);
@{{type}}['__bases__'] = B$tuple(@{{type}}['__bases__']);
@{{module}}['__bases__'] = B$tuple(@{{module}}['__bases__']);
@{{basestring}}['__bases__'] = B$tuple(@{{basestring}}['__bases__']);
@{{str}}['__bases__'] = B$tuple(@{{str}}['__bases__']);
@{{classmethod}}['__bases__'] = B$tuple(@{{classmethod}}['__bases__']);

@{{object}}['__dict__'] = B$dictproxy(@{{object}}['$dict']);
@{{tuple}}['__dict__'] = B$dictproxy(@{{tuple}}['$dict']);
@{{dictproxy}}['__dict__'] = B$dictproxy(@{{dictproxy}}['$dict']);
@{{type}}['__dict__'] = B$dictproxy(@{{type}}['$dict']);
@{{module}}['__dict__'] = B$dictproxy(@{{module}}['$dict']);
@{{basestring}}['__dict__'] = B$dictproxy(@{{basestring}}['$dict']);
@{{str}}['__dict__'] = B$dictproxy(@{{str}}['$dict']);
@{{classmethod}}['__dict__'] = B$dictproxy(@{{classmethod}}['$dict']);

@{{object}}['__name__'] = B$str("object");
@{{tuple}}['__name__'] = B$str("tuple");
@{{dictproxy}}['__name__'] = B$str("dictproxy");
@{{type}}['__name__'] = B$str("type");
@{{module}}['__name__'] = B$str("module");
@{{basestring}}['__name__'] = B$str("basestring");
@{{str}}['__name__'] = B$str("str");
@{{classmethod}}['__name__'] = B$str("classmethod");

@{{object}}['__class__'] = @{{type}};
@{{tuple}}['__class__'] = @{{type}};
@{{dictproxy}}['__class__'] = @{{type}};
@{{type}}['__class__'] = @{{type}};
@{{module}}['__class__'] = @{{type}};
@{{basestring}}['__class__'] = @{{type}};
@{{str}}['__class__'] = @{{type}};
@{{classmethod}}['__class__'] = @{{type}};

func(m$, null, @{{object}}, '__call__', 3, null, 'args', 'kwargs', null, $newext, true);
func(m$, null, @{{tuple}}, '__call__', 3, null, 'args', 'kwargs', null, $newext, true);
func(m$, null, @{{dictproxy}}, '__call__', 3, null, 'args', 'kwargs', null, $newext, true);
func(m$, null, @{{type}}, '__call__', 3, null, 'args', 'kwargs', null, $newext, true);
func(m$, null, @{{module}}, '__call__', 3, null, 'args', 'kwargs', null, $newext, true);
func(m$, null, @{{basestring}}, '__call__', 3, null, 'args', 'kwargs', null, $newext, true);
func(m$, null, @{{str}}, '__call__', 3, null, 'args', 'kwargs', null, $newext, true);
func(m$, null, @{{classmethod}}, '__call__', 3, null, 'args', 'kwargs', null, $newext, true);


// Add or complete some essential types
var B$__init__ = func(m$, null, @{{object}}, '__init__', 1, ['self'], 'args', 'kwargs', null, function($self) {
    return null;
});

@{{staticmethod}} = type(m$, 'staticmethod', [@{{object}}], {}, []);
func(m$, null, @{{staticmethod}}, '__init__', 1, ['self', 'function'], null, null, null, function($self, $function) {
    $self['im_func'] = $function;
    return N$;
});
func(m$, null, @{{staticmethod}}, '__str__', 1, ['self'], null, null, null, function($self) {
    if ($self['$inst'] === true) {
        return B$str("<staticmethod object of " + $self['im_func_']['__name__'] + ">");
    }
    return B$str("<type staticmethod >");
});
func(m$, null, @{{staticmethod}}, '__repr__', 1, ['self'], null, null, null, function($self) {
    if ($self['$inst'] === true) {
        return B$str("<staticmethod object of " + $self['im_func_']['__name__'] + ">");
    }
    return B$str("<type staticmethod >");
});

func(m$, null, @{{classmethod}}, '__init__', 1, ['self', 'function'], null, null, null, function($self, $function) {
    $self['im_func'] = $function;
    return N$;
});
func(m$, null, @{{classmethod}}, '__str__', 1, ['self'], null, null, null, function($self) {
    if ($self['$inst'] === true) {
        return B$str("<classmethod object of " + $self['im_func_']['__name__'] + ">");
    }
    return B$str("<type classmethod >");
});
func(m$, null, @{{classmethod}}, '__repr__', 1, ['self'], null, null, null, function($self) {
    if ($self['$inst'] === true) {
        return B$str("<classmethod object of " + $self['im_func_']['__name__'] + ">");
    }
    return B$str("<type classmethod >");
});

@{{instancemethod}} = type(m$, 'instancemethod', [@{{object}}], {}, []);
func(m$, null, @{{instancemethod}}, '__new__', 0, ['cls', 'function', 'instance', 'class'], null, null, null, function($cls, $function, $instance, $class) {
    var instance = function ( ) {
        var args = Array.prototype.slice.call(arguments);
        if (arguments.callee['__class__'] === @{{instancemethod}}) {
            if (arguments.callee['im_self'] !== null) {
                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
            }
        }
        var a = @{{_getattr}}(arguments.callee, '__call__');
        if (typeof a == "undefined") {
            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
        }
        if (args.length >= 3) {
            var len = args.length;
            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
            }
        }
        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
    }
    instance['toString'] = function ( ) {
        try {
            return @{{mcall}}(this, null, this, '__str__').valueOf();
        } catch (e) {
        }
        try {
            return "<" + this.__class__.__name__ + " instance>";
        } catch (e) {
        }
        return "<instance>";
    };
    instance['$inst'] = true;
    if (typeof $cls == "undefined") {
        debugger;
    }
    if (typeof $cls['__slots__'] == "undefined" || $cls['__slots__'].length > 0) {
        instance['__dict__'] = B$dict();
        instance['$dict'] = instance['__dict__']['__object'];
    }
    instance['__class__'] = $cls;
    instance['im_func'] = $function;
    instance['im_self'] = $instance;
    instance['im_class'] = $class;
    return instance;
});
func(m$, null, @{{instancemethod}}, '__init__', 1, ['self', 'function', 'instance', 'class'], null, null, null, function($self, $function, $instance, $class) {
    return null;
});
func(m$, null, @{{instancemethod}}, '__str__', 1, ['self'], null, null, null, function($self) {
    if ($self['$inst'] === true) {
        if ($self['im_self'] === null) {
            return B$str("<unbound method " + $self['im_class']['__name__'] + "." + $self['im_func']['__name__'] + ">");
        }
        if ($self['im_self']['$inst'] === true) {
            return B$str("<bound method " + $self['im_class']['__name__'] + "." + $self['im_func']['__name__'] + ">");
        }
        return B$str("<bound method type." + $self['im_func']['__name__'] + "of <" + $self['im_class']['__name__'] + ">>");
    }
    return B$str("<instance method>");
});
func(m$, null, @{{instancemethod}}, '__repr__', 1, ['self'], null, null, null, function($self) {
    if ($self['$inst'] === true) {
        if ($self['im_self'] === null) {
            return B$str("<unbound method " + $self['im_class']['__name__'] + "." + $self['im_func']['__name__'] + ">");
        }
        if ($self['im_self']['$inst'] === true) {
            return B$str("<bound method " + $self['im_class']['__name__'] + "." + $self['im_func']['__name__'] + ">");
        }
        return B$str("<bound method type." + $self['im_func']['__name__'] + "of <" + $self['im_class']['__name__'] + ">>");
    }
    return B$str("<instance method>");
});

// Complete the rest of the methods of the object type
func(m$, null, @{{object}}, '__setattr__', 1, ['self', 'name', 'value'], null, null, null, function($self, $name, $value) {
    if (typeof $name != 'string') {
        @{{raise}}($new(@{{TypeError}}, B$str("attribute name must be string")));
    }
    if ($self['$inst'] !== true) {
        @{{raise}}($new(@{{TypeError}}, B$str("can't apply this __setattr__ to type object")));
    }
    if ($self['__class__']['__slots__'] != "undefined") {
        if (typeof $self['__class__'][$name] != "undefined") {
            @{{raise}}($new(@{{AttributeError}}, B$str("'" + $self['__class__']['__name__'] + "' object has no attribute '" + $name + "'")));
        }
    }
    // TODO: check for __set__ on $self[$name]
    $self[$name] = $value;
    // TODO: func -> instancemethod
});
func(m$, null, @{{object}}, '__getattribute__', 1, ['self', 'name'], null, null, null, function($self, $name) {
    var v, mro$, name = $name.valueOf();
    if ($self['$inst'] !== true) {
        @{{raise}}($new(@{{TypeError}}, B$str("can't apply this __getattribute__ to type object")));
    }
    if ($name['__class__'] !== @{{str}} && typeof $name != 'string') {
        @{{raise}}($new(@{{TypeError}}, B$str("attribute name must be string")));
    }
    mro$ = $self['__class__']['__mro__'];
    for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
        if (typeof mro$[mro_i$][name] != "undefined") {
            v = mro$[mro_i$][name]
            break;
        }
        if (typeof mro$[mro_i$]['$dict'][name] != "undefined") {
            v = mro$[mro_i$]['$dict'][name];
            break;
        }
    }
    if (typeof v == "undefined") {
        return @{{raise}}($new(@{{AttributeError}}, B$str("'" + $self['__class__']['__name__'] + "' object has no attribute '" + name + "'")));
    }
    if ($self['$inst'] === false && $self['__class__'] !== @{{module}} && typeof v != "undefined" && typeof v['$inst'] != "undefined") {
        switch (v['__class__']) {
            case @{{function}}:
                var _new_dst$ = function ( ) {
                    var args = Array.prototype.slice.call(arguments);
                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                        if (arguments.callee['im_self'] !== null) {
                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                        }
                    }
                    var a = @{{_getattr}}(arguments.callee, '__call__');
                    if (typeof a == "undefined") {
                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                    }
                    if (args.length >= 3) {
                        var len = args.length;
                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                    }
                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                }
                _new_dst$['toString'] = function ( ) {
                    try {
                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                    } catch (e) {
                    }
                    try {
                        return "<" + this.__class__.__name__ + " instance>";
                    } catch (e) {
                    }
                    return "<instance>";
                };
                _new_dst$['$inst'] = true;
                if (typeof @{{instancemethod}} == "undefined") {
                    debugger;
                }
                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                    _new_dst$['__dict__'] = B$dict();
                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                }
                _new_dst$['__class__'] = @{{instancemethod}};
                _new_dst$['im_class'] = $self['$inst'] === true ? $self['__class__'] : $self;
                _new_dst$['im_func'] = v;
                _new_dst$['im_self'] = $self['$inst'] === true ? $self : null;
                v = _new_dst$;
                break;
            case @{{staticmethod}}:
                v = v['im_func'];
                break;
            case @{{classmethod}}:
                var _new_dst$ = function ( ) {
                    var args = Array.prototype.slice.call(arguments);
                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                        if (arguments.callee['im_self'] !== null) {
                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                        }
                    }
                    var a = @{{_getattr}}(arguments.callee, '__call__');
                    if (typeof a == "undefined") {
                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                    }
                    if (args.length >= 3) {
                        var len = args.length;
                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                    }
                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                }
                _new_dst$['toString'] = function ( ) {
                    try {
                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                    } catch (e) {
                    }
                    try {
                        return "<" + this.__class__.__name__ + " instance>";
                    } catch (e) {
                    }
                    return "<instance>";
                };
                _new_dst$['$inst'] = true;
                if (typeof @{{instancemethod}} == "undefined") {
                    debugger;
                }
                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                    _new_dst$['__dict__'] = B$dict();
                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                }
                _new_dst$['__class__'] = @{{instancemethod}};
                _new_dst$['im_class'] = $self['$inst'] === true ? $self['__class__'] : $self;
                _new_dst$['im_func'] = v['im_func'];
                _new_dst$['im_self'] = $self['$inst'] === true ? $self['__class__'] : $self;
                v = _new_dst$;
                break;
            case @{{bool}}: // Some known to be non-descriptors
            case @{{int}}:
            case @{{long}}:
            case @{{str}}:
                break;
            default:
                // check for __get__ method in v
                if (v['$inst'] === true) {
                    var get$ = @{{_getattr}}(v, '__get__');
                    if (typeof get$ != 'undefined') {
                        v = @{{fcall}}(this, null, get$, v, $self, $self['__class__']);
                    }
                }
                break;
        }
    }
    return v;
});
func(m$, null, @{{object}}, '__delattr__', 1, ['self', 'name'], null, null, null, function($self, $name) {
    if (typeof $name != 'string') {
        if ($name['__class__'] === @{{str}}) {
            $name = $name.__s;
        } else {
            @{{raise}}($new(@{{TypeError}}, B$str("attribute name must be string")));
        }
    }
    if ($self['$inst'] !== true) {
        @{{raise}}($new(@{{TypeError}}, B$str("can't apply this __delattr__ to type object")));
    }
    // TODO: check for __delete__ on $self[$name]
    if (typeof $self[$name] == "undefined") {
        @{{raise}}($new(@{{AttributeError}}, $name));
    }
    delete $self[$name];
});
func(m$, null, @{{object}}, '__str__', 1, ['self'], null, null, null, function($self) {
    var s;
    if ($self['$inst'] === true) {
        s = "instance of ";
        if (typeof self['__class__']['$dict'] != "undefined") {
            return B$str(s + self['__class__']['$dict']['__name__']);
        }
    } else if ($self['$inst'] === false) {
        s = "class ";
    } else {
        s = "javascript " + typeof self + " ";
    }
    if ($self['__module__']) {
        s += self['__module__'] + ".";
    }
    if (typeof self['__name__'] != "undefined") {
        return B$str(s + self['__name__']);
    }
    return B$str(s + "<unknown>");
});
func(m$, null, @{{object}}, '__repr__', 1, ['self'], null, null, null, function($self) {
    var s;
    if ($self['$inst'] === true) {
        s = "<instance of ";
    } else if ($self['$inst'] === false) {
        s = "<class ";
    } else {
        s = "<javascript " + typeof self + " ";
    }
    if ($self['__module__']) {
        s += self['__module__'] + ".";
    }
    if (typeof self['__name__'] != "undefined") {
        return B$str(s + self['__name__'] + ">");
    }
    return B$str(s + "<unknown>>");
});
var $next_hash_id$ = $min_int
    $hash_id_prefix$ = '#id#',
    $hash_id_name$ = '$H';
func(m$, null, @{{object}}, '__hash__', 1, ['self'], null, null, null, function($self) {
    if (typeof $self[$hash_id_name$] != "undefined" && $self[$hash_id_name$] !== null) {
        return $self[$hash_id_name$];
    }
    if ($next_hash_id$ == $max_int) {
        // I don't think we'll ever get here, but you never know...
        $next_hash_id$ = $min_int;
        $hash_id_prefix$ += '#';
    }
    $self[$hash_id_name$] = $hash_id_prefix$ + $next_hash_id$++;
    return $self[$hash_id_name$];
});

func(m$, null, g$, 'hash', 1, ['obj'], null, null, null, function($obj) {
    var h;
    if (typeof $obj['$inst'] != "undefined") {
        h = $obj[$hash_id_name$];
        if (typeof h == "undefined") {
            if ($obj['__class__'] === @{{str}}) {
                h = $obj['__s'].charAt(0) == '#' ? '#string#' + $obj['__s'] : $obj['__s'];
            } else {
                h = @{{mcall}}(this, null, $obj, '__hash__');
            }
        }
    } else if (typeof $obj == "string") {
        h = $obj.charAt(0) == '#' ? '#string#' + $obj : $obj;
    } else {
        h = '#' + typeof $obj + '#' + $obj;
    }
    return h;
});
init_short_names$(true);

@{{None}} = null;
@{{_NoneStr}} = B$str("None")
""")
# Need to define NoneType and None early, since it's used
# in several function definitions
class NoneType(object):
    def __str__(self):
        return "None"
    def __repr__(self):
        return "None"
JS("""
@{{__doc__}} = @{{None}} = $new(@{{NoneType}});
@{{None}}['valueOf'] = function() {return null;};
@{{None}}['toString'] = function() {return 'None';};
init_short_names$(true);



// Complete the module type
func(m$, null, @{{module}}, '__init__', 1, ['self', 'name'], null, null, [[]], function($self, $name) {
    if (typeof $name == 'string') {
        $self['__name__'] = typeofB$str($name);
    } else {
        $self['__name__'] = $name;
    }
    $self['__doc__'] = N$;
    $self['$module_init'] = function($name) {};
    $self['__class__'] = @{{module}};
    return N$;
});

// Complete the dictproxy type
func(m$, null, @{{dictproxy}}, '__new__', 0, ['cls', 'obj'], null, null, null, function($cls, $obj) {
    var instance = function ( ) {
        var args = Array.prototype.slice.call(arguments);
        if (arguments.callee['__class__'] === @{{instancemethod}}) {
            if (arguments.callee['im_self'] !== null) {
                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
            }
        }
        var a = @{{_getattr}}(arguments.callee, '__call__');
        if (typeof a == "undefined") {
            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
        }
        if (args.length >= 3) {
            var len = args.length;
            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
            }
        }
        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
    }
    instance['toString'] = function ( ) {
        try {
            return @{{mcall}}(this, null, this, '__str__').valueOf();
        } catch (e) {
        }
        try {
            return "<" + this.__class__.__name__ + " instance>";
        } catch (e) {
        }
        return "<instance>";
    };
    instance['$inst'] = true;
    if (typeof @{{dictproxy}} == "undefined") {
        debugger;
    }
    if (typeof @{{dictproxy}}['__slots__'] == "undefined" || @{{dictproxy}}['__slots__'].length > 0) {
        instance['__dict__'] = B$dict();
        instance['$dict'] = instance['__dict__']['__object'];
    }
    instance['__class__'] = @{{dictproxy}};
    instance['__object'] = $obj;
    instance['valueOf'] = function() {return this.__object;};
    instance['toString'] = function() {return this.__object.toString();};
    return instance;
});
func(m$, null, @{{dictproxy}}, '__init__', 1, ['self', 'iterable'], null, null, [[]], function($self, $obj) {
    return N$;
});
// TODO: methods for dictproxy (see dir(Foo.__dict__))

// Create the dict type
// class dict
@{{dict}} = type(m$, 'dict', [@{{object}}], {}, []);
func(m$, null, @{{dict}}, '__new__', 0, ['cls', 'iterable'], null, 'kwargs', [[]], function ($cls, $iterable, $kwargs) {
    var instance = function ( ) {
        var args = Array.prototype.slice.call(arguments);
        if (arguments.callee['__class__'] === @{{instancemethod}}) {
            if (arguments.callee['im_self'] !== null) {
                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
            }
        }
        var a = @{{_getattr}}(arguments.callee, '__call__');
        if (typeof a == "undefined") {
            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
        }
        if (args.length >= 3) {
            var len = args.length;
            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
            }
        }
        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
    }
    instance['toString'] = function ( ) {
        try {
            return @{{mcall}}(this, null, this, '__str__').valueOf();
        } catch (e) {
        }
        try {
            return "<" + this.__class__.__name__ + " instance>";
        } catch (e) {
        }
        return "<instance>";
    };
    instance['$inst'] = true;
    if (typeof $cls == "undefined") {
        debugger;
    }
    if (typeof $cls['__slots__'] == "undefined" || $cls['__slots__'].length > 0) {
        instance['__dict__'] = B$dict();
        instance['$dict'] = instance['__dict__']['__object'];
    }
    instance['__class__'] = $cls;
    instance['__object'] = {};
    instance['__object_hash'] = {};
    instance['__object_head'] = null;
    instance['__object_tail'] = null;
    instance['_length'] = 0;
    instance['valueOf'] = function() {return this.__object;};
    instance['getObject'] = function() {return this.__object;}; // backwards compatability TODO: remove this method
    instance['toString'] = function() {return this.__object.toString();};
    return instance;
});
func(m$, null, @{{dict}}, '__init__', 1, ['self', 'iterable'], null, 'kwargs', [[]], function ($self, $iterable, $kwargs) {
    var k, v, h, obj, objH, node, head, tail;
    head = tail = {'prev': null, 'next': null, 'key': null}
    obj = $self.__object;
    objH = $self.__object_hash;
    if ($iterable instanceof Array) {
        for (var i = 0; i < $iterable.length; i++) {
            if ($iterable[i] instanceof Array && $iterable[i].length == 2) {
                k = $iterable[i][0];
                v = $iterable[i][1];
                if (typeof k != "undefined" && typeof v != "undefined") {
                    h = @{{hash}}(k);
                    tail.next = node = {'prev': tail, 'next': null, 'key': k}
                    tail = node;
                    objH[h] = node;
                    obj[h] = v;
                    $self['_length']++;
                } else {
                    if (typeof k == "undefined") {
                        @{{raise}}($new(@{{TypeError}}, B$str("Invalid iterable (key is undefined)")));
                    }
                    @{{raise}}($new(@{{TypeError}}, B$str("Invalid iterable (value for '" + k + "' is undefined)")));
                }
            }
        }
    } else if ($iterable.valueOf() === null) {
        @{{raise}}($new(@{{TypeError}}, B$str("'NoneType' is not iterable")));
    } else if (typeof $iterable.__object_hash == 'object') {
        for (h in $iterable.__object_hash) {
            k = $iterable.__object_hash[h].key;
            v =  $iterable.__object[h];
            if (typeof k != "undefined" && typeof v != "undefined") {
                tail.next = node = {'prev': tail, 'next': null, 'key': k}
                tail = node;
                objH[h] = node;
                obj[h] = v;
                $self['_length']++;
            } else {
                if (typeof k == "undefined") {
                    @{{raise}}($new(@{{TypeError}}, B$str("Invalid iterable (key is undefined)")));
                }
                @{{raise}}($new(@{{TypeError}}, B$str("Invalid iterable (value for '" + k + "' is undefined)")));
            }
        }
    } else if (typeof $iterable['$inst'] == "undefined") {
        for (k in $iterable) {
            v = $iterable[k];
            if (typeof k != "undefined" && typeof v != "undefined") {
                h = @{{hash}}(k);
                tail.next = node = {'prev': tail, 'next': null, 'key': k}
                tail = node;
                objH[h] = node;
                obj[h] = v;
                $self['_length']++;
            } else {
                if (typeof k == "undefined") {
                    @{{raise}}($new(@{{TypeError}}, B$str("Invalid iterable (key is undefined)")));
                }
                @{{raise}}($new(@{{TypeError}}, B$str("Invalid iterable (value for '" + k + "' is undefined)")));
            }
        }
    } else {
        var iter, next, i, k, v, _stopiter = @{{stopiter}};
        iter = @{{fcall}}(this, null, @{{iter}}, null, $iterable);
        next = @{{getattr}}(iter, 'next');
        for (;;) {
            @{{stopiter}} = true;
            i = @{{fcall}}(this, null, next, iter);
            @{{stopiter}} = _stopiter;
            if (i === @{{StopIter}}) {
                break;
            }
            k = @{{getitem}}(i, @{{int_zero}});
            v = @{{getitem}}(i, @{{int_one}});
            @{{dict}}['$dict']['__setitem__']($self, k, v);
        }
    }
    if (typeof $kwargs != "undefined" && $kwargs !== null && $kwargs['_length'] > 0) {
        $iterable = $kwargs;
        for (h in $iterable.__object_hash) {
            k = $iterable.__object_hash[h].key;
            v =  $iterable.__object[h];
            if (typeof k != "undefined" && typeof v != "undefined") {
                tail.next = node = {'prev': tail, 'next': null, 'key': k}
                tail = node;
                objH[h] = node;
                obj[h] = v;
                $self['_length']++;
            } else {
                if (typeof k == "undefined") {
                    @{{raise}}($new(@{{TypeError}}, B$str("Invalid iterable (key is undefined)")));
                }
                @{{raise}}($new(@{{TypeError}}, B$str("Invalid iterable (value for '" + k + "' is undefined)")));
            }
        }
    }
    if (head !== tail) {
        $self.__object_head = head.next;
        $self.__object_head.prev = null;
        $self.__object_tail = tail;
    }
    return N$;
});
func(m$, null, @{{dict}}, 'clear', 1, ['self'], null, null, null, function ($self) {
    $self.__object = {};
    $self.__object_hash = {};
    $self.__object_head = null;
    $self.__object_tail = null;
    $self['_length'] = 0;
    return N$;
});
func(m$, null, @{{dict}}, 'copy', 1, ['self'], null, null, null, function ($self) {
    return $new(@{{dict}}, $self);
});
func(m$, null, @{{dict}}, '__hash__', 1, ['self'], null, null, null, function ($self) {
    @{{raise}}($new(@{{TypeError}}, B$str("dict objects are unhashable")));
});
func(m$, null, @{{dict}}, '__setitem__', 1, ['self', 'key', 'value'], null, null, null, function ($self, $key, $value) {
    if (typeof $value == "undefined") {
        @{{raise}}($new(@{{ValueError}}, B$str("Value for key '" + $key + "' is undefined")));
    }
    var node, h = @{{hash}}($key);
    if (typeof $self.__object_hash[h] == "undefined") {
        if ($self.__object_head === null) {
            $self.__object_head = $self.__object_tail = {'prev': null, 'next': null, 'key': $key};
        } else {
            node = {'prev': $self.__object_tail, 'next': null, 'key': $key}
            $self.__object_tail.next = node;
            $self.__object_tail = node;
        }
        $self['_length']++;
        $self.__object_hash[h] = $self.__object_tail;
    }
    $self.__object[h] = $value;
    return N$;
});
func(m$, null, @{{dict}}, '__getitem__', 1, ['self', 'key'], null, null, null, function ($self, $key) {
    var h = @{{hash}}($key);
    if (typeof $self.__object_hash[h] == "undefined") {
        @{{raise}}($new(@{{KeyError}}, $key));
    }
    return $self.__object[h];
});
func(m$, null, @{{dict}}, '__delitem__', 1, ['self', 'key'], null, null, null, function ($self, $key) {
    var node, h = @{{hash}}($key);
    node = $self.__object_hash[h];
    if (typeof node == "undefined") {
        @{{raise}}($new(@{{KeyError}}, $key));
    }
    if (node.prev === null) {
        $self.__object_head = node.next;
        if (node.next !== null) {
            $self.__object_head.prev = null;
        }
    } else if (node.next === null) {
        $self.__object_tail = node.prev;
        $self.__object_tail.next = null;
    } else {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }
    $self['_length']--;
    delete $self.__object_hash[h];
    delete $self.__object[h];
    delete node;
    return N$;
});
func(m$, null, @{{dict}}, 'setdefault', 1, ['self', 'key', 'value'], null, null, [N$], function ($self, $key, $value) {
    var h = @{{hash}}($key);
    if (typeof $self.__object_hash[h] == "undefined") {
        @{{dict}}['$dict']['__setitem__']($self, $key, $value);
        return $value;
    }
    return $self.__object[h];
});
func(m$, null, @{{dict}}, 'get', 1, ['self', 'key', 'value'], null, null, [N$], function ($self, $key, $value) {
    var h = @{{hash}}($key);
    if (typeof $self.__object_hash[h] == "undefined") {
        return $value;
    }
    return $self.__object[h];
});
func(m$, null, @{{dict}}, 'pop', 1, ['self', 'key', 'value'], null, null, [null], function ($self, $key, $value) {
    var h = @{{hash}}($key);
    if (typeof $self.__object_hash[h] == "undefined") {
        if ($value === null) {
            @{{raise}}($new(@{{KeyError}}, $key));
        }
        return $value;
    }
    $value = $self.__object[h];
    @{{dict}}['$dict']['__delitem__']($self, $key);
    return $value;
});
func(m$, null, @{{dict}}, 'popitem', 1, ['self'], null, null, [null], function ($self) {
    var k, v, h, node;
    if ($self['_length'] == 0) {
        @{{raise}}($new(@{{KeyError}}, B$str("popitem(): dictionary is empty")));
    }
    node = $self.__object_tail;
    k = node['key'];
    h = @{{hash}}(k);
    v = $self.__object[h];
    $self.__object_tail = node.prev;
    if ($self.__object_tail === null) {
        $self.__object_head = null;
    } else {
        $self.__object_tail.next = null;
    }
    $self['_length']--;
    delete $self.__object[h];
    delete $self.__object_hash[h];
    delete node;
    return $new(@{{tuple}}, [k, v]);
});
func(m$, null, @{{dict}}, '__nonzero__', 1, ['self'], null, null, null, function ($self) {
    if ($self['_length'] == 0) {
        return @{{False}};
    }
    return @{{True}};
});
func(m$, null, @{{dict}}, '__len__', 1, ['self'], null, null, null, function ($self) {
    return $new(@{{int}}, $self['_length']);
});
func(m$, null, @{{dict}}, '__contains__', 1, ['self', 'key'], null, null, null, function ($self, $key) {
    return typeof $self.__object_hash[@{{hash}}($key)] == "undefined" ? @{{False}} : @{{True}};
});
func(m$, null, @{{dict}}, 'has_key', 1, ['self', 'key'], null, null, null, function ($self, $key) {
    return typeof $self.__object_hash[@{{hash}}($key)] == "undefined" ? @{{False}} : @{{True}};
});
func(m$, null, @{{dict}}, 'keys', 1, ['self'], null, null, null, function ($self) {
    var i, keys = $new(@{{list}}, []),
        __array = keys.__array,
        objH = $self.__object_hash;
    i = 0;
    for (var h in objH) {
        __array[i] = objH[h]['key'];
        i ++;
    }
    return keys;
});
func(m$, null, @{{dict}}, 'fromkeys', 2, ['iterable', 'v'], null, null, [N$], function ($iterable, $v) {
    var iter, next, k, d = $new(@{{dict}}, []), _stopiter = @{{stopiter}};
    iter = @{{fcall}}(this, null, @{{iter}}, null, $iterable);
    next = @{{getattr}}(iter, 'next');
    for (;;) {
        @{{stopiter}} = true;
        k = @{{fcall}}(this, null, next, iter);
        @{{stopiter}} = _stopiter;
        if (k === @{{StopIter}}) {
            break;
        }
        @{{dict}}['$dict']['__setitem__'](d, k, $v);
    }
    return d;
});
func(m$, null, @{{dict}}, 'values', 1, ['self'], null, null, null, function ($self) {
    var i, values = $new(@{{list}}, []),
        __array = values.__array,
        obj = $self.__object;
    i = 0
    for (var h in obj) {
        __array[i++] = obj[h];
    }
    return values;
});
func(m$, null, @{{dict}}, 'items', 1, ['self'], null, null, null, function ($self) {
    var i, items = $new(@{{list}}, []),
        __array = items.__array,
        obj = $self.__object,
        objH = $self.__object_hash;
    i = 0;
    for (var h in obj) {
        __array[i++] = $new(@{{tuple}}, [objH[h]['key'], obj[h]]);
    }
    return items;
});
func(m$, null, @{{dict}}, '__iter__', 1, ['self'], null, null, null, function ($self) {
    return $new(@{{dictionary-keyiterator}}, $self);
});
func(m$, null, @{{dict}}, 'iterkeys', 1, ['self'], null, null, null, function ($self) {
    return $new(@{{dictionary-keyiterator}}, $self);
});
func(m$, null, @{{dict}}, 'itervalues', 1, ['self'], null, null, null, function ($self) {
    return $new(@{{dictionary-valueiterator}}, $self);
});
func(m$, null, @{{dict}}, 'iteritems', 1, ['self'], null, null, null, function ($self) {
    return $new(@{{dictionary-itemiterator}}, $self);
});
func(m$, null, @{{dict}}, '__cmp__', 1, ['self', 'y'], null, null, null, function ($self, $y) {
    if ($self['$inst'] === true) {
        if ($self['__class__']['__mro__'][$self['__class__']['__mro__'].length -2] === @{{dict}}) {
            var self_sKeys = new Array(),
                other_sKeys = new Array(),
                selfLen = 0,
                otherLen = 0,
                selfObj = $self.__object,
                otherObj = $y.__object,
                selfObjH = $self.__object_hash,
                otherObjH = $y.__object_hash;
            for (sKey in selfObjH) {
               self_sKeys[selfLen++] = sKey;
            }
            for (sKey in otherObjH) {
               other_sKeys[otherLen++] = sKey;
            }
            if (selfLen < otherLen) {
                return @{{int_minus_one}};
            }
            if (selfLen > otherLen) {
                return @{{int_one}};
            }
            self_sKeys.sort();
            other_sKeys.sort();
            var c, sKey, self_k, other_k;
            for (var idx = 0; idx < selfLen; idx++) {
                sKey = self_sKeys[idx];
                self_k = selfObjH[sKey]['key'];
                if (typeof otherObjH[sKey] == 'undefined') {
                    return @{{int_minus_one}};
                }
                other_k = otherObjH[sKey]['key'];
                c = @{{cmp}}(self_k, other_k);
                if (c.__v != 0) {
                    return c;
                }
                c = @{{cmp}}(selfObj[sKey], otherObj[sKey]);
                if (c.__v != 0) {
                    return c;
                }
            }
            return @{{int_zero}};
        }
    }
    @{{raise}}($new(@{{TypeError}}, B$str("dict.__cmp__(x,y) requires y to be a 'dict'")))
});

func(m$, null, @{{dict}}, '__str__', 1, ['self'], null, null, null, function ($self) {
    if ($self['$inst'] === false) {
        return B$str("<type '%s'>" % $self.__name__);
    } else if ($self['$inst'] === true) {
        var key, value, s = "", obj = $self['__object'], objH = $self['__object_hash'];
        for (var h in objH) {
            key = objH[h]['key'];
            value = obj[h];
            s += ", " + @{{repr}}(key) + ": " + @{{repr}}(value);
        }
        return B$str("{" + s.substring(2) + "}");
    }
    return B$str("" + $self);
});
func(m$, null, @{{dict}}, '__repr__', 1, ['self'], null, null, null, function ($self) {
    if (typeof $self['$inst'] == 'boolean') {
        var key, value, i,
            s = "",
            obj = $self['__object'],
            objH = $self['__object_hash'],
            hashes = [];
        i = 0;
        for (var h in objH) {
            hashes[i++] = h;
        }
        hashes.sort();
        for (i = 0 ; i < hashes.length; i++ ) {
            h = hashes[i];
            key = objH[h]['key'];
            value = obj[h];
            s += ", " + @{{repr}}(key) + ": " + @{{repr}}(value);
        }
        return B$str("{" + s.substring(2) + "}");
    }
    return B$str("" + $self);
});

// shortcut to dict.__setitem__ (used in setattr)
var dict$setitem = @{{dict}}['$dict']['__setitem__'];
var dict$delitem = @{{dict}}['$dict']['__delitem__'];


// Complete the tuple type
// class tuple
func(m$, null, @{{tuple}}, '__new__', 0, ['cls', 'iterable'], null, null, [[]], function ($cls, $iterable) {
    var instance = function ( ) {
        var args = Array.prototype.slice.call(arguments);
        if (arguments.callee['__class__'] === @{{instancemethod}}) {
            if (arguments.callee['im_self'] !== null) {
                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
            }
        }
        var a = @{{_getattr}}(arguments.callee, '__call__');
        if (typeof a == "undefined") {
            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
        }
        if (args.length >= 3) {
            var len = args.length;
            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
            }
        }
        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
    }
    instance['toString'] = function ( ) {
        try {
            return @{{mcall}}(this, null, this, '__str__').valueOf();
        } catch (e) {
        }
        try {
            return "<" + this.__class__.__name__ + " instance>";
        } catch (e) {
        }
        return "<instance>";
    };
    instance['$inst'] = true;
    if (typeof $cls == "undefined") {
        debugger;
    }
    if (typeof $cls['__slots__'] == "undefined" || $cls['__slots__'].length > 0) {
        instance['__dict__'] = B$dict();
        instance['$dict'] = instance['__dict__']['__object'];
    }
    instance['__class__'] = $cls;
    instance['__array'] = [];
    instance['valueOf'] = function() {return this.__array;};
    instance['toString'] = function() {return this['__class__']['$dict']['__str__'](this).valueOf();};
    return instance;
});
func(m$, null, @{{tuple}}, '__init__', 1, ['self', 'iterable'], null, null, [[]], function ($self, $iterable) {
    var iter, instance = $self;

    if ($iterable instanceof Array) {
        instance.__array = $iterable.slice();
        return N$;
    }
    if ($iterable.valueOf() === null) {
        @{{raise}}($new(@{{TypeError}}, B$str("'NoneType' is not iterable")));
    }
    iter = @{{_getattr}}($iterable, '__iter__');
    if (typeof iter != "undefined") {
        switch($iterable['__class__']) {
            case @{{tuple}}:
            case @{{list}}:
            case @{{tupleiterator}}:
            case @{{listiterator}}:
                instance.__array = $iterable.__array.slice();
                return N$;
            case @{{listreverseiterator}}:
                instance.__array = $iterable.__array.slice();
                instance.__array.reverse();
                return N$;
        }
        iter = @{{fcall}}(this, null, iter, $iterable);
        if (iter.__array instanceof Array) {
            instance.__array = iter.__array.slice();
            return N$;
        }
        var __array = instance.__array;
        var item, i = 0, stopiter = @{{stopiter}};
        for (;;) {
            @{{stopiter}} = true;
            item = @{{mcall}}(this, null, iter, 'next');
            @{{stopiter}} = stopiter;
            if (item === @{{StopIter}}) {
                break;
            }
            __array[i++] = item;
        }
        return N$;
    }
    @{{raise}}($new(@{{TypeError}}, B$str("'" + @{{repr}}($iterable) + "' is not iterable")));
});
func(m$, null, @{{tuple}}, '__len__', 1, ['self'], null, null, null, function($self) {
    return $new(@{{int}}, $self.__array.length);
});
func(m$, null, @{{tuple}}, '__str__', 1, ['self'], null, null, null, function($self) {
    if ($self.__array.length == 0) {
        return B$str("()");
    }
    var s = '(';
    for (var i = 0; i < $self.__array.length; i++) {
        s += @{{repr}}($self.__array[i]) + ', ';
    }
    s = s.substring(0, s.length - ($self.__array.length == 1 ? 1 : 2));
    return B$str(s + ")");
});
func(m$, null, @{{tuple}}, '__repr__', 1, ['self'], null, null, null, function($self) {
    if ($self.__array.length == 0) {
        return B$str("()");
    }
    var s = '(';
    for (var i = 0; i < $self.__array.length; i++) {
        s += @{{repr}}($self.__array[i]) + ', ';
    }
    return B$str(s.substring(0, s.length - ($self.__array.length == 1 ? 1 : 2)) + ')');
});
func(m$, null, @{{tuple}}, '__hash__', 1, ['self'], null, null, null, function($self) {
    var hash = '$tuple$';
    for (var i = 0; i < $self.__array.length; i++) {
        hash += ',' + @{{hash}}($self.__array[i]);
    }
    return hash;
});
func(m$, null, @{{tuple}}, '__getitem__', 1, ['self', 'index'], null, null, null, function($self, $index) {
    if (typeof $index == 'number' || @{{isinstance}}($index, [@{{int}}, @{{long}}]).__v) {
        var index = typeof $index != 'number' ? $index.valueOf() : ($index < 0 ? Math.ceil($index) : Math.floor($index));
        if (index < 0) index += $self.__array.length;
        if (index < 0 || index >= $self.__array.length) {
            @{{raise}}($new(@{{IndexError}}, B$str(_typeof($self) + " index out of range")));
        }
        return $self.__array[index];
    }
    if ($index['__class__'] === @{{slice}}) {
        var start = $index['$dict']['start'].valueOf(),
            stop = $index['$dict']['stop'].valueOf(),
            step = $index['$dict']['step'].valueOf(),
            __array = [];
        if (start === null) start = 0;
        if (stop === null || stop > $self.__array.length) stop = $self.__array.length;
        if (step === null) step = 1;
        for (; start < stop; start += step) {
            __array.push($self.__array[start]);
        }
        return $new($self['__class__'], __array);
    }
    @{{raise}}($new(@{{TypeError}}, B$str(_typeof($self) + " indices must be integers, not " + typeof $index)));
});
func(m$, null, @{{tuple}}, '__getslice__', 1, ['self', 'lower', 'upper'], null, null, null, function($self, $lower, $upper) {
    if (typeof $lower == 'number' || @{{isinstance}}($lower, [@{{int}}, @{{long}}]).__v) {
        if (typeof $upper == 'number' || @{{isinstance}}($upper, [@{{int}}, @{{long}}]).__v) {
            var lower = $lower.valueOf(),
                upper = $upper.valueOf();
            if (upper < 0) {
                upper += $self.__array.length;
            }
            return B$tuple($self.__array.slice(lower, upper));
        }
    }
    @{{raise}}($new(@{{TypeError}}, B$str(_typeof($self) + " indices must be integers, not " + typeof $index)));
});
func(m$, null, @{{tuple}}, '__iter__', 1, ['self'], null, null, null, function ($self) {
    return $new(@{{tupleiterator}}, $self);
});
func(m$, null, @{{tuple}}, '__contains__', 1, ['self', 'value'], null, null, null, function ($self, $value) {
    return $self.__array.indexOf($value) >= 0 ? @{{True}} : @{{False}};
});
func(m$, null, @{{tuple}}, 'count', 1, ['self', 'value'], null, null, null, function ($self, $value) {
    var n = 0, __array = $self.__array;
    for (var i = 0; i < __array.length; i++) {
        if (@{{cmp}}(__array[i], $value)) {
            n++;
        }
    }
    return $new(@{{int}}, n);
});
// lazy... implement __cmp__ in stead of __eq__ and friends
func(m$, null, @{{tuple}}, '__cmp__', 1, ['self', 'y'], null, null, null, function ($self, $y) {
    if ($y['__class__'] !== @{{tuple}}) {
        if (@{{isinstance}}($y, @{{tuple}}) !== @{{True}}) {
            return @{{int_one}};
        }
    }
    var n1 = $self.__array.length,
        n2 = $y.__array.length,
        a1 = $self.__array,
        a2 = $y.__array,
        n, c;
    n = (n1 < n2 ? n1 : n2);
    for (var i = 0; i < n; i++) {
        c = @{{cmp}}(a1[i], a2[i]);
        if (c !== @{{int_zero}}) return c;
    }
    if (n1 < n2) return @{{int_minus_one}};
    if (n1 > n2) return @{{int_one}};
    return @{{int_zero}};
});
func(m$, null, @{{tuple}}, '__add__', 1, ['self', 'value'], null, null, null, function ($self, $value) {
    if ($value['__class__'] !== @{{tuple}}) {
        return @{{raise}}($new(@{{TypeError}}, B$str("can only concatenate tuple (not '" + _typeof($value) + "') to tuple")));
    }
    return B$tuple($self.__array.slice(0).concat($value.__array));
});


var empty_tuple = B$tuple([]);

//@{{NoneType}} = type(m$, 'tuple', [@{{object}}], {}, []);
// Initialize the short names, i.e., those that are available
init_short_names$(true);

@{{tupleiterator}} = type(m$, 'tupleiterator', [@{{object}}], {}, []);
func(m$, null, @{{tupleiterator}}, '__init__', 1, ['self', 'iterable'], null, null, null, function ($self, $iterable) {
    $self['index'] = 0;
    $self['__array'] = $iterable.__array;
    return N$;
});
func(m$, null, @{{tupleiterator}}, '__iter__', 1, ['self'], null, null, null, function ($self) {
    return $self;
});
func(m$, null, @{{tupleiterator}}, '__length_hint__', 1, ['self'], null, null, null, function ($self) {
    return $new(@{{int}}, $self.__array.length - $self['index']);
});
func(m$, null, @{{tupleiterator}}, 'next', 1, ['self'], null, null, null, function ($self) {
    if ($self['index'] >= $self.__array.length) {
        return @{{raise}}(@{{StopIteration}});
    }
    return $self.__array[$self.index++];
});

@{{listiterator}} = type(m$, 'listiterator', [@{{object}}], {}, []);
func(m$, null, @{{listiterator}}, '__init__', 1, ['self', 'iterable'], null, null, null, function ($self, $iterable) {
    $self['index'] = 0;
    $self['__array'] = $iterable.__array;
    return N$;
});
func(m$, null, @{{listiterator}}, '__iter__', 1, ['self'], null, null, null, function ($self) {
    return $self;
});
func(m$, null, @{{listiterator}}, '__length_hint__', 1, ['self'], null, null, null, function ($self) {
    if ($self['index'] >= $self.__array.length) {
        return @{{int_zero}};
    }
    return $new(@{{int}}, $self.__array.length - $self['index']);
});
func(m$, null, @{{listiterator}}, 'next', 1, ['self'], null, null, null, function ($self) {
    if ($self['index'] >= $self.__array.length) {
        return @{{raise}}(@{{StopIteration}});
    }
    return $self.__array[$self.index++];
});


@{{listreverseiterator}} = type(m$, 'listreverseiterator', [@{{object}}], {}, []);
func(m$, null, @{{listreverseiterator}}, '__init__', 1, ['self', 'iterable'], null, null, null, function ($self, $iterable) {
    $self['__array'] = $iterable.__array;
    $self['index'] = $iterable.__array.length;
    return N$;
});
func(m$, null, @{{listreverseiterator}}, '__iter__', 1, ['self'], null, null, null, function ($self) {
    return $self;
});
func(m$, null, @{{listreverseiterator}}, '__length_hint__', 1, ['self'], null, null, null, function ($self) {
    if ($self['index'] > $self.__array.length ||
        $self['index']  <= 1) {
        return @{{int_zero}};
    }
    return $new(@{{int}}, $self['index']);
});
func(m$, null, @{{listreverseiterator}}, 'next', 1, ['self'], null, null, null, function ($self) {
    if ($self['index'] < 1) {
        return @{{raise}}(@{{StopIteration}});
    }
    return $self.__array[--$self.index];
});

@{{dictionary-keyiterator}} = type(m$, 'dictionary-keyiterator', [@{{object}}], {}, []);
func(m$, null, @{{dictionary-keyiterator}}, '__init__', 1, ['self', 'iterable'], null, null, null, function ($self, $iterable) {
    $self['index'] = 0;
    $self['iterable'] = $iterable;
    $self['node'] = $iterable.__object_head;
    $self['_length'] = $iterable._length;
    return N$;
});
func(m$, null, @{{dictionary-keyiterator}}, '__iter__', 1, ['self'], null, null, null, function ($self) {
    return $self;
});
func(m$, null, @{{dictionary-keyiterator}}, '__length_hint__', 1, ['self'], null, null, null, function ($self) {
    if ($self._length != $self['iterable']._length ) {
        @{{raise}}($new(@{{RuntimeError}}, B$str("dictionary changed size during iteration")));
    }
    if ($self['index'] >= $self._length) {
        return @{{int_zero}};
    }
    return $new(@{{int}}, $self._length - $self['index']);
});
func(m$, null, @{{dictionary-keyiterator}}, 'next', 1, ['self'], null, null, null, function ($self) {
    var key;
    if ($self._length == $self['iterable']._length ) {
        if ($self['node'] === null) {
            return @{{raise}}(@{{StopIteration}});
        }
        if ($self['index'] < $self._length) {
            $self['index']++;
            key = $self['node']['key'];
            $self['node'] = $self['node'].next;
            return key;
        }
    }
    @{{raise}}($new(@{{RuntimeError}}, B$str("dictionary changed size during iteration")));
});

@{{dictionary-valueiterator}} = type(m$, 'dictionary-valueiterator', [@{{object}}], {}, []);
func(m$, null, @{{dictionary-valueiterator}}, '__init__', 1, ['self', 'iterable'], null, null, null, function ($self, $iterable) {
    $self['index'] = 0;
    $self['iterable'] = $iterable;
    $self['node'] = $iterable.__object_head;
    $self['_length'] = $iterable._length;
    return N$;
});
func(m$, null, @{{dictionary-valueiterator}}, '__iter__', 1, ['self'], null, null, null, function ($self) {
    return $self;
});
func(m$, null, @{{dictionary-valueiterator}}, '__length_hint__', 1, ['self'], null, null, null, function ($self) {
    if ($self._length != $self['iterable']._length ) {
        @{{raise}}($new(@{{RuntimeError}}, B$str("dictionary changed size during iteration")));
    }
    if ($self['index'] >= $self._length) {
        return @{{int_zero}};
    }
    return $new(@{{int}}, $self._length - $self['index']);
});
func(m$, null, @{{dictionary-valueiterator}}, 'next', 1, ['self'], null, null, null, function ($self) {
    var value;
    if ($self._length == $self['iterable']._length ) {
        if ($self['node'] === null) {
            return @{{raise}}(@{{StopIteration}});
        }
        if ($self['index'] < $self._length) {
            $self['index']++;
            value = $self['iterable']['__object'][@{{hash}}($self['node']['key'])];
            $self['node'] = $self['node'].next;
            return value;
        }
    }
    @{{raise}}($new(@{{RuntimeError}}, B$str("dictionary changed size during iteration")));
});

@{{dictionary-itemiterator}} = type(m$, 'dictionary-itemiterator', [@{{object}}], {}, []);
func(m$, null, @{{dictionary-itemiterator}}, '__init__', 1, ['self', 'iterable'], null, null, null, function ($self, $iterable) {
    $self['index'] = 0;
    $self['iterable'] = $iterable;
    $self['node'] = $iterable.__object_head;
    $self['_length'] = $iterable._length;
    return N$;
});
func(m$, null, @{{dictionary-itemiterator}}, '__iter__', 1, ['self'], null, null, null, function ($self) {
    return $self;
});
func(m$, null, @{{dictionary-itemiterator}}, '__length_hint__', 1, ['self'], null, null, null, function ($self) {
    if ($self._length != $self['iterable']._length ) {
        @{{raise}}($new(@{{RuntimeError}}, B$str("dictionary changed size during iteration")));
    }
    if ($self['index'] >= $self._length) {
        return @{{int_zero}};
    }
    return $new(@{{int}}, $self._length - $self['index']);
});
func(m$, null, @{{dictionary-itemiterator}}, 'next', 1, ['self'], null, null, null, function ($self) {
    var key, value;
    if ($self._length == $self['iterable']._length ) {
        if ($self['node'] === null) {
            return @{{raise}}(@{{StopIteration}});
        }
        if ($self['index'] < $self._length) {
            $self['index']++;
            key = $self['node']['key'];
            value = $self['iterable']['__object'][@{{hash}}(key)];
            $self['node'] = $self['node'].next;
            return B$tuple([key, value]);
        }
    }
    @{{raise}}($new(@{{RuntimeError}}, B$str("dictionary changed size during iteration")));
});


// class str
func(m$, null, @{{str}}, '__new__', 0, ['cls', 'value'], null, null, [''], function(cls, value) {
    if (typeof value == "undefined") {
        if (typeof cls == 'string') {
            value = cls;
            cls = @{{str}};
        } else {
            @{{raise}}($new(@{{TypeError}}, B$str("str: value is undefined")));
        }
    } else if (value['__class__'] === cls) {
        return value;
    }
    var v = value.valueOf();
    var new_str = function ( ) {
        var args = Array.prototype.slice.call(arguments);
        if (arguments.callee['__class__'] === @{{instancemethod}}) {
            if (arguments.callee['im_self'] !== null) {
                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
            }
        }
        var a = @{{_getattr}}(arguments.callee, '__call__');
        if (typeof a == "undefined") {
            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
        }
        if (args.length >= 3) {
            var len = args.length;
            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
            }
        }
        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
    }
    new_str['toString'] = function ( ) {
        try {
            return @{{mcall}}(this, null, this, '__str__').valueOf();
        } catch (e) {
        }
        try {
            return "<" + this.__class__.__name__ + " instance>";
        } catch (e) {
        }
        return "<instance>";
    };
    new_str['$inst'] = true;
    if (typeof cls == "undefined") {
        debugger;
    }
    if (typeof cls['__slots__'] == "undefined" || cls['__slots__'].length > 0) {
        new_str['__dict__'] = B$dict();
        new_str['$dict'] = new_str['__dict__']['__object'];
    }
    new_str['__class__'] = cls;
    new_str['__s'] = v;
    new_str['valueOf'] = function() {return this.__s;};
    new_str['toString'] = function() {return this.__s.toString();};
    if (typeof value == 'string') {
        return new_str;
    }
    if (value === null) {
        return @{{None}}.__str__(@{{None}});
    }
    if (typeof value =='boolean') {
        return value ? @{{True}}.__str__(@{{True}}) : @{{False}}.__str__(@{{False}});
    }
    var mro$;
        v = [][1];
        var mro$ = value['__mro__'];
        var _meth_src = value;
        switch (value['$inst']) {
            case true:
                if (value['__class__'] === @{{module}}) {
                    v = value['$dict']['__str__'];
                    break;
                } else if (value['__class__'] === @{{function}}) {
                    switch ('__str__'.charAt(0)) {
                        case 'i':
                        case '_':
                            v = value['__str__'];
                    }
                    break;
                }
                var _noraise$ = @{{noraise}};
                var ga;
                mro$ = value['__class__']['__mro__'];
                for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                    var _mro$ = mro$[mro_i$];
                    var ga = _mro$['__getattribute__'];
                    if (typeof ga == "undefined") {
                        if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattribute__'];
                    }
                    if (value['__class__']['$inst'] === false && value['__class__'] !== @{{module}} && typeof value != "undefined" && typeof value['$inst'] != "undefined") {
                        switch (ga['__class__']) {
                            case @{{function}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = value['$inst'] === true ? value['__class__'] : value;
                                _new_dst$['im_func'] = ga;
                                _new_dst$['im_self'] = value['$inst'] === true ? value : null;
                                ga = _new_dst$;
                                break;
                            case @{{staticmethod}}:
                                ga = ga['im_func'];
                                break;
                            case @{{classmethod}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = value['$inst'] === true ? value['__class__'] : value;
                                _new_dst$['im_func'] = ga['im_func'];
                                _new_dst$['im_self'] = value['$inst'] === true ? value['__class__'] : value;
                                ga = _new_dst$;
                                break;
                            case @{{bool}}: // Some known to be non-descriptors
                            case @{{int}}:
                            case @{{long}}:
                            case @{{str}}:
                                break;
                            default:
                                // check for __get__ method in ga
                                if (ga['$inst'] === true) {
                                    var get$ = @{{_getattr}}(ga, '__get__');
                                    if (typeof get$ != 'undefined') {
                                        ga = @{{fcall}}(this, null, get$, ga, value, value['__class__']);
                                    }
                                }
                                break;
                        }
                    }
                    @{{noraise}} = @{{AttributeError}};
                    v = @{{fcall}}(this, null, ga, _mro$, '__str__');
                    @{{noraise}} = _noraise$;
                    if (v === @{{AttributeError}}) {
                        v = [][1];
                    }
                    _meth_src = value['__class__'];
                    value = value['__class__'];
                    break;
                }
                if (typeof v == "undefined") {
                    if (typeof value['$dict'] != "undefined") {
                        v = value['$dict']['__str__'];
                        if (typeof v != "undefined") {
                            if (v !== {}['__str__']) {
                                break;
                            }
                            v = [][1];
                        }
                    }
                    switch ('__str__'.charAt(0)) {
                        case 'i':
                        case '_':
                            v = value['__str__'];
                    }
                    if (typeof v != "undefined") {
                        break;
                    }
                }
            case false:
                if (typeof v == "undefined") {
                    var _mro$, ga;
                    if (value['$inst'] === true) {
                        _meth_src = value['__class__'];
                    } else {
                        switch ('__str__'.charAt(0)) {
                            case 'i':
                            case '_':
                                v = value['__str__'];
                        }
                        if (typeof v != "undefined") {
                            break;
                        }

                    }
                    if (typeof v == "undefined") {
                        for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            v = _mro$['$dict']['__str__'];
                            if (typeof v != "undefined") {
                                if (v !== {}['__str__']) {
                                    break;
                                }
                                v = [][1];
                            }
                            switch ('__str__'.charAt(0)) {
                                case 'i':
                                case '_':
                                    v = _mro$['__str__'];
                            }
                            if (typeof v != "undefined") {
                                break;
                            }
                        }
                    }
                    if (typeof v == "undefined" && '__str__' !== '__get__') {
                        for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                continue;
                            }
                            ga = _mro$['$dict']['__getattr__'];
                            if (value['__class__']['$inst'] === false && value['__class__'] !== @{{module}} && typeof value != "undefined" && typeof value['$inst'] != "undefined") {
                                switch (ga['__class__']) {
                                    case @{{function}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = value['$inst'] === true ? value['__class__'] : value;
                                        _new_dst$['im_func'] = ga;
                                        _new_dst$['im_self'] = value['$inst'] === true ? value : null;
                                        ga = _new_dst$;
                                        break;
                                    case @{{staticmethod}}:
                                        ga = ga['im_func'];
                                        break;
                                    case @{{classmethod}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = value['$inst'] === true ? value['__class__'] : value;
                                        _new_dst$['im_func'] = ga['im_func'];
                                        _new_dst$['im_self'] = value['$inst'] === true ? value['__class__'] : value;
                                        ga = _new_dst$;
                                        break;
                                    case @{{bool}}: // Some known to be non-descriptors
                                    case @{{int}}:
                                    case @{{long}}:
                                    case @{{str}}:
                                        break;
                                    default:
                                        // check for __get__ method in ga
                                        if (ga['$inst'] === true) {
                                            var get$ = @{{_getattr}}(ga, '__get__');
                                            if (typeof get$ != 'undefined') {
                                                ga = @{{fcall}}(this, null, get$, ga, value, value['__class__']);
                                            }
                                        }
                                        break;
                                }
                            }
                            @{{noraise}} = @{{AttributeError}};
                            v = @{{fcall}}(this, null, ga, _mro$, '__str__');
                            @{{noraise}} = _noraise$;
                            if (v === @{{AttributeError}}) {
                                v = [][1];
                            }
                            // TODO : unbind v ?
                            break;
                        }
                    }
                }
                break;
            default:
                v = value['__str__'];
                if (typeof v == "undefined" && typeof value['$dict'] != "undefined") {
                    v = value['$dict']['__str__'];
                }
        }
    if (typeof v == "undefined") {
        new_str['__s'] = String(value);
        return new_str;
    }
    if (v['__class__'] === cls) {
        return v;
    }
    if (typeof v['__class__'] != "undefined") {
        v = @{{fcall}}(this, null, v, value, value);
        if (v['__class__'] === @{{str}}) {
            return v;
        }
        if (typeof v == 'string') {
            new_str['__s'] = v;
        } else {
            @{{raise}}($new(@{{TypeError}}, B$str("__str__ returned non-string")));
        }
    } else if (typeof v == 'function') {
        if (typeof v['__name__'] != "undefined") {
            new_str['__s'] = "<function " + v['__name__'] + ">";
        } else {
            new_str['__s'] = "<javascript function " + v['name'] + ">";
        }
    } else {
        new_str['__s'] = "<javascript " + typeof v + ">";
    }
    return new_str;
});

func(m$, null, @{{str}}, '__len__', 1, ['self'], null, null, null, function ($self) {
    return $new(@{{int}}, $self.__s.length);
});

func(m$, null, @{{str}}, 'find', 1, ['self', 'sub', 'start', 'end'], null, null, [N$, N$], function($self, $sub, $start, $end) {
    var self = $self.valueOf();
    var sub = $sub.valueOf();
    var start = $start.valueOf();
    var end = $end.valueOf();
    var pos = self.indexOf(sub, start);
    if (typeof end != 'number' || pos + sub.length <= end) {
        switch (pos) {
            case -1:
                break;
            case 0:
                return @{{int_zero}}
            case 1:
                return @{{int_one}}
            default:
                return $new(@{{int}}, pos);
        }
    }
    return @{{int_minus_one}};
});

func(m$, null, @{{str}}, 'rfind', 1, ['self', 'sub', 'start', 'end'], null, null, [N$, N$], function($self, $sub, $start, $end) {
    var self = $self.valueOf();
    var sub = $sub.valueOf();
    var start = $start.valueOf();
    var end = $end.valueOf();
    var pos;
    if (typeof start == 'number') {
        /* *sigh* - python rfind goes *RIGHT*, NOT left */
        pos = self.substring(start).lastIndexOf(sub);
        if (pos == -1) {
            return @{{int_minus_one}};
        }
        pos += start;
    } else {
        pos = self.lastIndexOf(sub);
    }
    if (typeof end == 'number') {
        if (pos + sub.length > end) return @{{int_minus_one}};
    }
    return $new(@{{int}}, pos);
});

func(m$, null, @{{str}}, 'index', 1, ['self', 'sub', 'start', 'end'], null, null, [N$, N$], function($self, $sub, $start, $end) {
    var i = @{{str}}['$dict']['find']($self, $sub, $start, $end);
    if (i.__v < 0) {
        @{{raise}}($new(@{{ValueError}}, B$str("substring not found")));
    }
    return i;
});

func(m$, null, @{{str}}, 'rindex', 1, ['self', 'sub', 'start', 'end'], null, null, [N$, N$], function($self, $sub, $start, $end) {
    var i = @{{str}}['$dict']['rfind']($self, $sub, $start, $end);
    if (i.__v < 0) {
        @{{raise}}($new(@{{ValueError}}, B$str("substring not found")));
    }
    return i;
});

func(m$, null, @{{str}}, 'partition', 1, ['self', 'sep'], null, null, null, function($self, $sep) {
    var i = @{{str}}['$dict']['find']($self, $sep, N$, N$);
    if (i.__v < 0) {
        return B$tuple([$self, @{{empty_str}}, @{{empty_str}}]);
    }
    var self = $self.valueOf(), sep = $sep.valueOf();
    return B$tuple([B$str(self.substring(0, i.__v)), $sep, B$str(self.substring(sep.length + i.__v))])
});

func(m$, null, @{{str}}, 'rpartition', 1, ['self', 'sep'], null, null, null, function($self, $sep) {
    var i = @{{str}}['$dict']['rfind']($self, $sep, N$, N$);
    if (i.__v < 0) {
        return B$tuple([@{{empty_str}}, @{{empty_str}}, $self]);
    }
    var self = $self.valueOf(), sep = $sep.valueOf();
    return B$tuple([B$str(self.substring(0, i.__v)), $sep, B$str(self.substring(sep.length + i.__v))])
});

func(m$, null, @{{str}}, 'count', 1, ['self', 'sub', 'start', 'end'], null, null, [N$], function(self, sub, start, end) {
    self = self.valueOf();
    start = start.valueOf();
    end = end.valueOf();
    var pos, count = 0, n = sub.length;
    if (typeof start != 'number') start = 0;
    if (typeof end == "undefined") end = self.length;
    while (start < end) {
        pos = self.find(sub, start, end);
        if (pos < 0) break;
        count ++;
        start = pos + n;
    }
    return $new(@{{int}}, count);
});

func(m$, null, @{{str}}, 'join', 1, ['self', 'iterable'], null, null, [N$], function($self, $iterable) {
    var s = $self.valueOf();
    var data = $iterable.valueOf();
    var text="";

    if (data instanceof Array) {
        if (data.length > 0) {
            text = data[0].valueOf()
            for (var i = 1; i < data.length; i++) {
               text += s + data[i].valueOf();
            }
        }
    } else if (typeof $iterable.__iter__ == 'function') {
        if ($iterable.__array instanceof Array) {
            text = $iterable.__array.join(s);
        } else {
            var iter = $iterable.__iter__();
            if (typeof iter.__array == 'object') {
                return iter.__array.join(s);
            }
            data = [];
            var item, i = 0;
            if (typeof iter.$genfunc == 'function') {
                while (typeof (item=iter.next(true)) != "undefined") {
                    data[i++] = item;
                }
            } else {
                try {
                    while (true) {
                        data[i++] = iter.next();
                    }
                }
                catch (e) {
                    if (e.__name__ != 'StopIteration') throw e;
                }
            }
            text = data.join(s);
        }
    }
    return $new(@{{str}}, text);
});

func(m$, null, @{{str}}, 'isdigit', 1, ['self'], null, null, [N$], function(self) {
    return self.valueOf().match(/^\d+$/g) !== null ? @{{True}} : @{{False}};
});

func(m$, null, @{{str}}, 'isalnum', 1, ['self'], null, null, [N$], function(self) {
    return self.valueOf().match(/^[a-zA-Z\d]+$/g) !== null ? @{{True}} : @{{False}};
});

func(m$, null, @{{str}}, 'isalpha', 1, ['self'], null, null, [N$], function(self) {
    return self.valueOf().match(/^[a-zA-Z]+$/g) !== null ? @{{True}} : @{{False}};
});

func(m$, null, @{{str}}, 'isupper', 1, ['self'], null, null, [N$], function(self) {
    return self.valueOf().match(/[a-z]/g) === null ? @{{True}} : @{{False}};
});

func(m$, null, @{{str}}, 'replace', 1, ['self', 'old', 'replace', 'count'], null, null, [N$], function(self, old, replace, count) {
    self = self.valueOf();
    old = old.valueOf();
    replace = replace.valueOf();
    count = count.valueOf();
    var do_max=false;
    var start=0;
    var text="";
    var pos=0;

    if (typeof old != 'string') {
        text = self.replace(old, replace);
    } else {
        if (typeof count == 'number') do_max=true;

        while (start<self.length) {
            if (do_max && !count--) break;

            pos=self.indexOf(old, start);
            if (pos<0) break;

            text+=self.substring(start, pos) + replace;
            start=pos+old.length;
        }
        if (start<self.length) text+=self.substring(start);
    }
    return $new(@{{str}}, text);
});

func(m$, null, @{{str}}, '__contains__', 1, ['self', 's'], null, null, null, function($self, $s) {
    return $self.valueOf().indexOf($s)>=0 ? @{{True}} : @{{False}};
});


func(m$, null, @{{str}}, 'split', 1, ['self', 'sep', 'maxsplit'], null, null, [N$, N$], function($self, $sep, $maxsplit) {
    var subject = $self.valueOf();
    var sep = $sep.valueOf();
    var maxsplit = $maxsplit.valueOf();
    var items=[];
    var do_max=false;
    var start=0;
    var pos=0;

    if (sep === null || typeof sep == "undefined") {
        sep=" ";
        if (subject.length == 0) {
            return $new(@{{list}}, items);
        }
        subject = subject.replace(/^\s+/, "");
        subject = subject.replace(/\s+$/, "");
        subject = subject.replace(/\s+/g, sep);
    }
    else if (typeof maxsplit == 'number') do_max=true;

    if (subject.length == 0) {
        items.push(B$str(''));
        return $new(@{{list}}, items);
    }

    while (start<subject.length) {
        if (do_max && !maxsplit--) break;

        pos=subject.indexOf(sep, start);
        if (pos<0) break;

        items.push(B$str(subject.substring(start, pos)));
        start=pos+sep.length;
    }
    if (start<=subject.length) items.push(B$str(subject.substring(start)));

    return $new(@{{list}}, items);
});

func(m$, null, @{{str}}, 'rsplit', 1, ['self', 'sep', 'maxsplit'], null, null, [N$], function($self, $sep, $maxsplit) {
    var subject = self.valueOf();
    var sep = sep.valueOf();
    var maxsplit = maxsplit.valueOf();
    var items=[];
    var do_max=false;
    var pos=0;

    if (sep === null || typeof sep == "undefined") {
        sep=" ";
        if (subject.length == 0) {
            return $new(@{{list}}, items);
        }
        subject = subject.replace(/^\s+/, "");
        subject = subject.replace(/\s+$/, "");
        subject = subject.replace(/\s+/g, sep);
    }
    else if (typeof maxsplit == 'number') do_max=true;

    if (subject.length == 0) {
        items.push(B$str(''));
        return $new(@{{list}}, items);
    }

    while (subject.length > 0) {
        if (do_max && !maxsplit--) break;

        pos=subject.lastIndexOf(sep);
        if (pos<0) break;

        items.push(B$str(subject.substr(pos+sep.length)));
        subject = subject.substr(0, pos);
    }
    if (subject.length > 0) items.push(B$str(subject));
    items.reverse()

    return $new(@{{list}}, items);
});

if (typeof "a"[0] == "undefined" ) {
    // IE: cannot do "abc"[idx]
    func(m$, null, @{{str}}, '__iter__', 1, ['self'], null, null, null, function(self) {
        self = self.valueOf();
        var i = 0;
        return {
            'next': function(noStop) {
                if (i >= self.length) {
                    if (noStop === true) {
                        return;
                    }
                    return @{{raise}}(@{{StopIteration}});
                }
                return $new(@{{str}}, self.charAt(i++));
            },
            '__iter__': function() {
                return this;
            }
        };
    });
} else {
    func(m$, null, @{{str}}, '__iter__', 1, ['self'], null, null, null, function(self) {
        self = self.valueOf();
        var i = 0;
        return {
            '__array': self,
            'next': function(noStop) {
                if (i >= self.length) {
                    if (noStop === true) {
                        return;
                    }
                    return @{{raise}}(@{{StopIteration}});
                }
                return $new(@{{str}}, self.charAt(i++));
            },
            '__iter__': function() {
                return this;
            }
        };
    });
}

func(m$, null, @{{str}}, 'strip', 1, ['self', 'chars'], null, null, [N$], function(self, chars) {
    self = self.valueOf();
    chars = chars.valueOf();
    if (typeof chars == 'string') {
        self = self.replace(new RegExp("^[" + chars + "]+"), "");
        self = self.replace(new RegExp("[" + chars + "]+$"), "");
    } else {
        self = self.replace(/^\s+/, "");
        self = self.replace(/\s+$/, "");
    }
    return $new(@{{str}}, self);
});

func(m$, null, @{{str}}, 'lstrip', 1, ['self', 'chars'], null, null, [N$], function(self, chars) {
    self = self.valueOf();
    chars = chars.valueOf();
    if (typeof chars == 'string') {
        self = self.replace(new RegExp("^[" + chars + "]+"), "");
    } else {
        self = self.replace(/^\s+/, "");
    }
    return $new(@{{str}}, self);
});

func(m$, null, @{{str}}, 'rstrip', 1, ['self', 'chars'], null, null, [N$], function(self, chars) {
    self = self.valueOf();
    chars = chars.valueOf();
    if (typeof chars == 'string') {
        self = self.replace(new RegExp("[" + chars + "]+$"), "");
    } else {
        self = self.replace(/\s+$/, "");
    }
    return $new(@{{str}}, self);
});

func(m$, null, @{{str}}, 'startswith', 1, ['self', 'prefix', 'start', 'end'], null, null, [N$, N$], function(self, prefix, start, end) {
    self = self.valueOf();
    prefix = prefix.valueOf();
    start = start.valueOf();
    end = end.valueOf();
    // FIXME: accept tuples as suffix (since 2.5)
    if (typeof start != 'number') start = 0;
    if (typeof end != 'number') end = self.length;

    if ((end - start) < prefix.length) return @{{False}};
    if (self.substr(start, prefix.length) == prefix) return @{{True}};
    return @{{False}};
});

func(m$, null, @{{str}}, 'endswith', 1, ['self', 'suffix', 'start', 'end'], null, null, [N$, N$], function(self, suffix, start, end) {
    self = self.valueOf();
    suffix = suffix.valueOf();
    start = start.valueOf();
    end = end.valueOf();
    // FIXME: accept tuples as suffix (since 2.5)
    if (typeof start != 'number') start = 0;
    if (typeof end != 'number') end = self.length;

    if ((end - start) < suffix.length) return @{{False}};
    if (self.substr(end - suffix.length, suffix.length) == suffix) return @{{True}};
    return @{{False}};
});

func(m$, null, @{{str}}, 'ljust', 1, ['self', 'width', 'fillchar'], null, null, [N$, N$], function($self, $width, $fillchar) {
    var s = $self.valueOf();
    fillchar = $fillchar.valueOf();
    width = $width.valueOf();
    switch ($width.__number__) {
        case 0x02:
        case 0x04:
            break;
        default:
            if (typeof width == 'number') {
                if (Math.floor(width) == width) break;
            }
        case 0x01:
            return @{{raise}}($new(@{{TypeError}}, B$str("an integer is required, got " + _typeof($width))));
    }
    if (typeof fillchar != 'string') fillchar = ' ';
    if (typeof(fillchar) != 'string' ||
        fillchar.length != 1) {
        return @{{raise}}($new(@{{TypeError}}, B$str("ljust() argument 2 must be char, not " + _typeof($fillchar))));
    }
    if (s.length >= width) return $self;
    return $new(@{{str}}, s + new Array(width+1 - s.length).join(fillchar));
});

func(m$, null, @{{str}}, 'rjust', 1, ['self', 'width', 'fillchar'], null, null, [N$, N$], function($self, $width, $fillchar) {
    var s = $self.valueOf();
    fillchar = $fillchar.valueOf();
    width = $width.valueOf();
    switch ($width.__number__) {
        case 0x02:
        case 0x04:
            break;
        default:
            if (typeof width == 'number') {
                if (Math.floor(width) == width) break;
            }
        case 0x01:
            return @{{raise}}($new(@{{TypeError}}, B$str("an integer is required, got " + _typeof($width))));
    }
    if (typeof fillchar != 'string') fillchar = ' ';
    if (typeof(fillchar) != 'string' ||
        fillchar.length != 1) {
        return @{{raise}}($new(@{{TypeError}}, B$str("rjust() argument 2 must be char, not " + _typeof($fillchar))));
    }
    if (s.length >= width) return $self;
    return B$str(new Array(width+1 - s.length).join(fillchar) + s);
});

func(m$, null, @{{str}}, 'center', 1, ['self', 'width', 'fillchar'], null, null, [N$, N$], function(self, width, fillchar) {
    var s = self.valueOf();
    fillchar = fillchar.valueOf();
    switch (width.__number__) {
        case 0x02:
        case 0x04:
            width = width.valueOf();
            break;
        case 0x01:
            if (Math.floor(width) == width) break;
        default:
            if (typeof width.valueOf() != 'number') {
                @{{raise}}($new(@{{TypeError}}, B$str("an integer is required (got '" + width + "')")));
            }
            width = width.valueOf();
    }
    if (typeof fillchar != 'string') fillchar = ' ';
    if (typeof(fillchar) != 'string' ||
        fillchar.length != 1) {
        @{{raise}}($new(@{{TypeError}}, B$str("center() argument 2 must be char, not " + typeof(fillchar))));
    }
    if (s.length >= width) return self;
    var padlen = width - s.length;
    var right = Math.ceil(padlen / 2);
    var left = padlen - right;
    return $new(@{{str}}, new Array(left+1).join(fillchar) + s + new Array(right+1).join(fillchar));
});


func(m$, null, @{{str}}, '__getslice__', 1, ['self', 'lower', 'upper'], null, null, null, function($self, $lower, $upper) {
    var self = $self.valueOf();
    var lower = $lower.valueOf();
    var upper = $upper.valueOf();
    if (lower === null) {
        lower = 0;
    } else if (lower < 0) {
        lower = self.length + lower;
    }
    if (upper === null) {
        upper=self.length;
    } else if (upper < 0) {
       upper = self.length + upper;
    }
    return B$str(self.substring(lower, upper));
});

func(m$, null, @{{str}}, '__getitem__', 1, ['self', 'idx'], null, null, null, function($self, $idx) {
    var self = $self.valueOf();
    var idx = $idx.valueOf()
    if (idx < 0) idx += self.length;
    if (idx < 0 || idx > self.length) {
        @{{raise}}($new(@{{IndexError}}, B$str("string index out of range")));
    }
    return B$str(self.charAt(idx));
});

func(m$, null, @{{str}}, '__setitem__', 1, ['self', 'idx', 'val'], null, null, null, function(self, idx, val) {
    @{{raise}}($new(@{{TypeError}}, B$str("'str' object does not support item assignment")));
});

func(m$, null, @{{str}}, 'upper', 1, ['self'], null, null, null, function(self) {
    var src = self.valueOf();
    var dst = src.toUpperCase();
    if (src == dst) {
        return self;
    }
    return $new(@{{str}}, dst);
});

func(m$, null, @{{str}}, 'lower', 1, ['self'], null, null, null, function(self) {
    var src = self.valueOf();
    var dst = src.toLowerCase();
    if (src == dst) {
        return self;
    }
    return $new(@{{str}}, dst);
});

func(m$, null, @{{str}}, 'capitalize', 1, ['self'], null, null, null, function(self) {
    var src = self.valueOf();
    var dst = src.charAt(0).toUpperCase() + src.substring(1);
    if (src == dst) {
        return self;
    }
    return $new(@{{str}}, dst);
});

func(m$, null, @{{str}}, 'zfill', 1, ['self', 'width'], null, null, null, function($self, $width) {
    return @{{str}}['$dict']['rjust']($self, $width, '0');
});

func(m$, null, @{{str}}, '__mod__', 1, ['self', 'y'], null, null, null, function($self, $y) {
    return @{{sprintf}}($self, $y);
});

func(m$, null, @{{str}}, '__add__', 1, ['self', 'y'], null, null, null, function(self, y) {
    self = self.valueOf();
    y = y.valueOf();
    if (typeof y != "string") {
        @{{raise}}($new(@{{TypeError}}, B$str("cannot concatenate 'str' and non-str objects")));
    }
    return $new(@{{str}}, self + y);
});

func(m$, null, @{{str}}, '__mul__', 1, ['self', 'y'], null, null, null, function(self, y) {
    self = self.valueOf();
    switch (y.__number__) {
        case 0x02:
        case 0x04:
            y = y.valueOf();
            break;
        case 0x01:
            if (Math.floor(y) == y) break;
        default:
            if (typeof y.valueOf() != 'number') {
                @{{raise}}($new(@{{TypeError}}, B$str("can't multiply sequence by non-int of type 'str'")));
            }
            y = y.valueOf();
    }
    var s = '';
    while (y-- > 0) {
        s += self;
    }
    return $new(@{{str}}, s);
});

func(m$, null, @{{str}}, '__str__', 1, ['self'], null, null, null, function(self) {
    if (self.$inst === false) {
        return B$str("<type '" + self['$dict']['__name__'] + "'>");
    }
    return self;
});

func(m$, null, @{{str}}, '__repr__', 1, ['self'], null, null, null, function(self) {
    if (self.$inst === false) {
        return B$str("<type '" + self['$dict']['__name__'] + "'>");
    }
    return B$str("'" + self.valueOf() + "'");
});

@{{str}}['$dict']['__rmul__'] = @{{str}}['$dict']['__mul__'];
""")



class float(object):

    JS("""
    f$['__slots__'] = [];
    func(m$, null, f$, '__new__', 0, ['cls', 'value'], null, null, [0.0], function($cls, $value) {
        if ($value.__class__ === $cls) {
            return $value
        }
        var v = $value.valueOf();
        if (typeof v == 'string') {
            v = v.replace(/^\s+/, "");
            if (v === "") {
                @{{raise}}($new(@{{ValueError}}, B$str("empty string for float()")));
            }
            v = Number(v);
        } else if (typeof v != 'number') {
            @{{raise}}($new(@{{TypeError}}, B$str("float() argument must be a string or a number")));
        }
        if (isNaN(v)) {
            @{{raise}}($new(@{{ValueError}}, B$str("invalid literal for float(): " + $value.valueOf())));
        }
    var instance = function ( ) {
        var args = Array.prototype.slice.call(arguments);
        if (arguments.callee['__class__'] === @{{instancemethod}}) {
            if (arguments.callee['im_self'] !== null) {
                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
            }
        }
        var a = @{{_getattr}}(arguments.callee, '__call__');
        if (typeof a == "undefined") {
            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
        }
        if (args.length >= 3) {
            var len = args.length;
            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
            }
        }
        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
    }
    instance['toString'] = function ( ) {
        try {
            return @{{mcall}}(this, null, this, '__str__').valueOf();
        } catch (e) {
        }
        try {
            return "<" + this.__class__.__name__ + " instance>";
        } catch (e) {
        }
        return "<instance>";
    };
    instance['$inst'] = true;
    if (typeof @{{float}} == "undefined") {
        debugger;
    }
    if (typeof @{{float}}['__slots__'] == "undefined" || @{{float}}['__slots__'].length > 0) {
        instance['__dict__'] = B$dict();
        instance['$dict'] = instance['__dict__']['__object'];
    }
    instance['__class__'] = @{{float}};
        instance['__r'] = v; // real
        //instance['__i'] = 0.0; // imag
        instance['__number__'] = 0x01;
        instance['valueOf'] = function() {return this.__r;};
        instance['toString'] = function() {return this.__r.toString();};
        return instance;
    });
    func(m$, null, f$, '__abs__', 1, ['self'], null, null, null, function($self) {
        var v = $self.valueOf();
        return v < 0 ? $new(@{{float}}, -v) : $self;
    });
    func(m$, null, f$, '__add__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        return $new(@{{float}}, $self + $y);
    });
    func(m$, null, f$, '__div__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        return $new(@{{float}}, Math.floor($self + $y));
    });
    func(m$, null, f$, '__divmod__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        if ($y == 0) @{{raise}}($new(@{{ZeroDivisionError}}, B$str("float divmod()")));
        var f = Math.floor($self / $y);
        return $new(@{{tuple}}, [$new(@{{float}}, f), $new(@{{float}}, $self - f * $y)]);
    });
    func(m$, null, f$, '__eq__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        return $self == y ? @{{True}} : @{{False}};
    });
    func(m$, null, f$, '__floordiv__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        if ($y == 0) @{{raise}}($new(@{{ZeroDivisionError}}, B$str("float divmod()")));
        $self /= $y;
        return $new(@{{float}}, $self < 0 ? Math.ceil($self) : Math.floor($self));
    });
    func(m$, null, f$, '__ge__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        return $self >= y ? @{{True}} : @{{False}};
    });
    func(m$, null, f$, '__gt__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        return $self > y ? @{{True}} : @{{False}};
    });
    func(m$, null, f$, '__hash__', 1, ['self'], null, null, null, function($self) {
        return "#float#" + self.valueOf();
    });
    func(m$, null, f$, '__int__', 1, ['self'], null, null, null, function($self) {
        return $new(@{{int}}, $self.valueOf());
    });
    func(m$, null, f$, '__le__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        return $self <= y ? @{{True}} : @{{False}};
    });
    func(m$, null, f$, '__long__', 1, ['self'], null, null, null, function($self) {
        return $new(@{{long}}, $self.valueOf());
    });
    func(m$, null, f$, '__lt__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        return $self < y ? @{{True}} : @{{False}};
    });
    func(m$, null, f$, '__mod__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        return $new(@{{float}}, $self % $y);
    });
    func(m$, null, f$, '__mul__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        return $new(@{{float}}, $self * $y);
    });
    func(m$, null, f$, '__ne__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        return $self != y ? @{{True}} : @{{False}};
    });
    func(m$, null, f$, '__neg__', 1, ['self'], null, null, null, function($self) {
        $self = $self.valueOf();
        return $new(@{{float}}, -$self);
    });
    func(m$, null, f$, '__nonzero__', 1, ['self'], null, null, null, function($self) {
        return $self.valueOf() == 0 ? @{{False}} : @{{True}};
    });
    func(m$, null, f$, '__pos__', 1, ['self'], null, null, null, function($self) {
        return $new(@{{float}}, $self);
    });
    func(m$, null, f$, '__pow__', 1, ['self', 'y', 'z'], null, null, [null], function($self, $y, $z) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        if (typeof $z == "undefined" || $z == null) {
            return $new(@{{float}}, Math.pow($self,  $y));
        }
        $z = $z.valueOf();
        if (isNaN(z)) return @{{NotImplemented}};
        return $new(@{{float}}, Math.pow($self, $) % $z);
    });
    /*
    func(m$, null, f$, '__radd__', 1, ['self'], null, null, null, function($self) {
    });
    func(m$, null, f$, '__rdiv__', 1, ['self'], null, null, null, function($self) {
    });
    */
    func(m$, null, f$, '__rdivmod__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        if ($y == 0) @{{raise}}($new(@{{ZeroDivisionError}}, B$str("float divmod()")));
        var f = Math.floor($y / $self);
        return $new(@{{tuple}}, [$new(@{{float}}, f), $new(@{{float}}, $y - f * $self)]);
    });
    func(m$, null, f$, '__repr__', 1, ['self'], null, null, null, function($self) {
        $self = $self.valueOf();
        return $new(@{{str}}, $self.toString());
    });
    /*
    func(m$, null, f$, '__rfloordiv__', 1, ['self'], null, null, null, function($self) {
    });
    func(m$, null, f$, '__rmod__', 1, ['self'], null, null, null, function($self) {
    });
    func(m$, null, f$, '__rmul__', 1, ['self'], null, null, null, function($self) {
    });
    func(m$, null, f$, '__rpow__', 1, ['self'], null, null, null, function($self) {
    });
    func(m$, null, f$, '__rsub__', 1, ['self'], null, null, null, function($self) {
    });
    func(m$, null, f$, '__rtruediv__', 1, ['self'], null, null, null, function($self) {
    });
    */
    func(m$, null, f$, '__str__', 1, ['self'], null, null, null, function($self) {
        return B$str($self.valueOf().toString());
    });
    func(m$, null, f$, '__sub__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        return $new(@{{float}}, $self - $y);
    });
    func(m$, null, f$, '__truediv__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        $self = $self.valueOf();
        $y = $y.valueOf();
        if (typeof $y != 'number') {
            return @{{NotImplemented}};
        }
        return $new(@{{float}}, $self / $y);
    });
    func(m$, null, f$, '__trunc__', 1, ['self'], null, null, null, function($self) {
        $self = $self.valueOf();
        return $new(@{{float}}, $self < 0 ? Math.ceil($self) : Math.floor($self));
    });
    /*
    func(m$, null, f$, 'as_integer_ratio', 1, ['self'], null, null, null, function($self) {
    });
    func(m$, null, f$, 'conjugate', 1, ['self'], null, null, null, function($self) {
    });
    func(m$, null, f$, 'fromhex', 1, ['self'], null, null, null, function($self) {
    });
    func(m$, null, f$, 'hex', 1, ['self'], null, null, null, function($self) {
    });
    */
    func(m$, null, f$, 'imag', 1, ['self'], null, null, null, function($self) {
        return $new(@{{float}}, 0.0);
    });
    func(m$, null, f$, 'is_integer', 1, ['self'], null, null, null, function($self) {
        $self = $self.valueOf();
        if ($self == Math.floor($self) || $self == Math.ceil($self)) {
            return @{{True}};
        }
        return @{{False}};
    });
    func(m$, null, f$, 'real', 1, ['self'], null, null, null, function($self) {
        return $new(@{{float}}, self.__r);
    });""")


class int(object):
    # Some dummy defines to enable the translator to
    # refer to these at the end (e.g. __div__ = __floordiv__)
    __floordiv__ = __rfloordiv__ = None
    JS("""
    f$['__slots__'] = [];
    func(m$, null, f$, '__new__', 0, ['cls', 'value', 'radix'], null, null, [null], function(cls, value, radix) {
        var i, v = value.valueOf();
        var new_int = function ( ) {
            var args = Array.prototype.slice.call(arguments);
            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                if (arguments.callee['im_self'] !== null) {
                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                }
            }
            var a = @{{_getattr}}(arguments.callee, '__call__');
            if (typeof a == "undefined") {
                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
            }
            if (args.length >= 3) {
                var len = args.length;
                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                }
            }
            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
        }
        new_int['toString'] = function ( ) {
            try {
                return @{{mcall}}(this, null, this, '__str__').valueOf();
            } catch (e) {
            }
            try {
                return "<" + this.__class__.__name__ + " instance>";
            } catch (e) {
            }
            return "<instance>";
        };
        new_int['$inst'] = true;
        if (typeof cls == "undefined") {
            debugger;
        }
        if (typeof cls['__slots__'] == "undefined" || cls['__slots__'].length > 0) {
            new_int['__dict__'] = B$dict();
            new_int['$dict'] = new_int['__dict__']['__object'];
        }
        new_int['__class__'] = cls;
        new_int['__v'] =  v;
        new_int['__number__'] =  0x02,
        new_int['valueOf'] = function() {return this.__v;};
        new_int['toString'] = function() {return this.__v.toString();};
        if (radix === null || typeof radix == "undefined") {
            // handle some javascript types
            switch (typeof value) {
                case 'number':
                    v = v > 0 ? Math.floor(v) : Math.ceil(v);
                    if (v == -1) {
                        return @{{int_minus_one}};
                    } else if (v == 0) {
                        return @{{int_zero}};
                    } else if (v == 1) {
                        return @{{int_one}};
                    }
                    new_int['__v'] =  v;
                    return new_int;
                case 'boolean':
                    return v ? @{{int_one}} : @{{int_zero}};
                case "undefined":
                    @{{raise}}($new(@{{TypeError}}, B$str("int() takes at least 1 argument")));
            }
            // TODO: change usage of value.__number__
            // to value.__class__
            switch (value.__number__) {
                case 0x01: // float
                    v = v > 0 ? Math.floor(v) : Math.ceil(v);
                    if (v == -1) {
                        return @{{int_minus_one}};
                    } else if (v == 0) {
                        return @{{int_zero}};
                    } else if (v == 1) {
                        return @{{int_one}};
                    }
                    new_int['__v'] =  v;
                    return new_int;
                    break;
                case 0x02: // int
                    return value;
                case 0x04: // long
                    if (!($min_int <= v && v <= $max_int))
                        return value;
                    if (v == -1) {
                        return @{{int_minus_one}};
                    } else if (v == 0) {
                        return @{{int_zero}};
                    } else if (v == 1) {
                        return @{{int_one}};
                    }
                    return new_int;
                default:
                    if (v === 'true') {
                        return @{{int_one}};
                    } else if (v === 'true') {
                        return @{{int_zero}};
                    }
                    // check whether we've got an object that has its own __int__() method
                    var mro$;
                        i = [][1];
                        var mro$ = value['__mro__'];
                        var _meth_src = value;
                        switch (value['$inst']) {
                            case true:
                                if (value['__class__'] === @{{module}}) {
                                    i = value['$dict']['__int__'];
                                    break;
                                } else if (value['__class__'] === @{{function}}) {
                                    switch ('__int__'.charAt(0)) {
                                        case 'i':
                                        case '_':
                                            i = value['__int__'];
                                    }
                                    break;
                                }
                                var _noraise$ = @{{noraise}};
                                var ga;
                                mro$ = value['__class__']['__mro__'];
                                for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                                    var _mro$ = mro$[mro_i$];
                                    var ga = _mro$['__getattribute__'];
                                    if (typeof ga == "undefined") {
                                        if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                                            continue;
                                        }
                                        ga = _mro$['$dict']['__getattribute__'];
                                    }
                                    if (value['__class__']['$inst'] === false && value['__class__'] !== @{{module}} && typeof value != "undefined" && typeof value['$inst'] != "undefined") {
                                        switch (ga['__class__']) {
                                            case @{{function}}:
                                                var _new_dst$ = function ( ) {
                                                    var args = Array.prototype.slice.call(arguments);
                                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                        if (arguments.callee['im_self'] !== null) {
                                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                        }
                                                    }
                                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                                    if (typeof a == "undefined") {
                                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                    }
                                                    if (args.length >= 3) {
                                                        var len = args.length;
                                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                        }
                                                    }
                                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                                _new_dst$['toString'] = function ( ) {
                                                    try {
                                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                    } catch (e) {
                                                    }
                                                    try {
                                                        return "<" + this.__class__.__name__ + " instance>";
                                                    } catch (e) {
                                                    }
                                                    return "<instance>";
                                                };
                                                _new_dst$['$inst'] = true;
                                                if (typeof @{{instancemethod}} == "undefined") {
                                                    debugger;
                                                }
                                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                    _new_dst$['__dict__'] = B$dict();
                                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                                }
                                                _new_dst$['__class__'] = @{{instancemethod}};
                                                _new_dst$['im_class'] = value['$inst'] === true ? value['__class__'] : value;
                                                _new_dst$['im_func'] = ga;
                                                _new_dst$['im_self'] = value['$inst'] === true ? value : null;
                                                ga = _new_dst$;
                                                break;
                                            case @{{staticmethod}}:
                                                ga = ga['im_func'];
                                                break;
                                            case @{{classmethod}}:
                                                var _new_dst$ = function ( ) {
                                                    var args = Array.prototype.slice.call(arguments);
                                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                        if (arguments.callee['im_self'] !== null) {
                                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                        }
                                                    }
                                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                                    if (typeof a == "undefined") {
                                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                    }
                                                    if (args.length >= 3) {
                                                        var len = args.length;
                                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                        }
                                                    }
                                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                                _new_dst$['toString'] = function ( ) {
                                                    try {
                                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                    } catch (e) {
                                                    }
                                                    try {
                                                        return "<" + this.__class__.__name__ + " instance>";
                                                    } catch (e) {
                                                    }
                                                    return "<instance>";
                                                };
                                                _new_dst$['$inst'] = true;
                                                if (typeof @{{instancemethod}} == "undefined") {
                                                    debugger;
                                                }
                                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                    _new_dst$['__dict__'] = B$dict();
                                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                                }
                                                _new_dst$['__class__'] = @{{instancemethod}};
                                                _new_dst$['im_class'] = value['$inst'] === true ? value['__class__'] : value;
                                                _new_dst$['im_func'] = ga['im_func'];
                                                _new_dst$['im_self'] = value['$inst'] === true ? value['__class__'] : value;
                                                ga = _new_dst$;
                                                break;
                                            case @{{bool}}: // Some known to be non-descriptors
                                            case @{{int}}:
                                            case @{{long}}:
                                            case @{{str}}:
                                                break;
                                            default:
                                                // check for __get__ method in ga
                                                if (ga['$inst'] === true) {
                                                    var get$ = @{{_getattr}}(ga, '__get__');
                                                    if (typeof get$ != 'undefined') {
                                                        ga = @{{fcall}}(this, null, get$, ga, value, value['__class__']);
                                                    }
                                                }
                                                break;
                                        }
                                    }
                                    @{{noraise}} = @{{AttributeError}};
                                    i = @{{fcall}}(this, null, ga, _mro$, '__int__');
                                    @{{noraise}} = _noraise$;
                                    if (i === @{{AttributeError}}) {
                                        i = [][1];
                                    }
                                    _meth_src = value['__class__'];
                                    value = value['__class__'];
                                    break;
                                }
                                if (typeof i == "undefined") {
                                    if (typeof value['$dict'] != "undefined") {
                                        i = value['$dict']['__int__'];
                                        if (typeof i != "undefined") {
                                            if (i !== {}['__int__']) {
                                                break;
                                            }
                                            i = [][1];
                                        }
                                    }
                                    switch ('__int__'.charAt(0)) {
                                        case 'i':
                                        case '_':
                                            i = value['__int__'];
                                    }
                                    if (typeof i != "undefined") {
                                        break;
                                    }
                                }
                            case false:
                                if (typeof i == "undefined") {
                                    var _mro$, ga;
                                    if (value['$inst'] === true) {
                                        _meth_src = value['__class__'];
                                    } else {
                                        switch ('__int__'.charAt(0)) {
                                            case 'i':
                                            case '_':
                                                i = value['__int__'];
                                        }
                                        if (typeof i != "undefined") {
                                            break;
                                        }

                                    }
                                    if (typeof i == "undefined") {
                                        for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                                            _mro$ = mro$[mro_i$];
                                            i = _mro$['$dict']['__int__'];
                                            if (typeof i != "undefined") {
                                                if (i !== {}['__int__']) {
                                                    break;
                                                }
                                                i = [][1];
                                            }
                                            switch ('__int__'.charAt(0)) {
                                                case 'i':
                                                case '_':
                                                    i = _mro$['__int__'];
                                            }
                                            if (typeof i != "undefined") {
                                                break;
                                            }
                                        }
                                    }
                                    if (typeof i == "undefined" && '__int__' !== '__get__') {
                                        for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                                            _mro$ = mro$[mro_i$];
                                            if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                                continue;
                                            }
                                            ga = _mro$['$dict']['__getattr__'];
                                            if (value['__class__']['$inst'] === false && value['__class__'] !== @{{module}} && typeof value != "undefined" && typeof value['$inst'] != "undefined") {
                                                switch (ga['__class__']) {
                                                    case @{{function}}:
                                                        var _new_dst$ = function ( ) {
                                                            var args = Array.prototype.slice.call(arguments);
                                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                                if (arguments.callee['im_self'] !== null) {
                                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                                }
                                                            }
                                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                                            if (typeof a == "undefined") {
                                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                            }
                                                            if (args.length >= 3) {
                                                                var len = args.length;
                                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                                }
                                                            }
                                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                        }
                                                        _new_dst$['toString'] = function ( ) {
                                                            try {
                                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                            } catch (e) {
                                                            }
                                                            try {
                                                                return "<" + this.__class__.__name__ + " instance>";
                                                            } catch (e) {
                                                            }
                                                            return "<instance>";
                                                        };
                                                        _new_dst$['$inst'] = true;
                                                        if (typeof @{{instancemethod}} == "undefined") {
                                                            debugger;
                                                        }
                                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                            _new_dst$['__dict__'] = B$dict();
                                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                                        }
                                                        _new_dst$['__class__'] = @{{instancemethod}};
                                                        _new_dst$['im_class'] = value['$inst'] === true ? value['__class__'] : value;
                                                        _new_dst$['im_func'] = ga;
                                                        _new_dst$['im_self'] = value['$inst'] === true ? value : null;
                                                        ga = _new_dst$;
                                                        break;
                                                    case @{{staticmethod}}:
                                                        ga = ga['im_func'];
                                                        break;
                                                    case @{{classmethod}}:
                                                        var _new_dst$ = function ( ) {
                                                            var args = Array.prototype.slice.call(arguments);
                                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                                if (arguments.callee['im_self'] !== null) {
                                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                                }
                                                            }
                                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                                            if (typeof a == "undefined") {
                                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                            }
                                                            if (args.length >= 3) {
                                                                var len = args.length;
                                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                                }
                                                            }
                                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                        }
                                                        _new_dst$['toString'] = function ( ) {
                                                            try {
                                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                            } catch (e) {
                                                            }
                                                            try {
                                                                return "<" + this.__class__.__name__ + " instance>";
                                                            } catch (e) {
                                                            }
                                                            return "<instance>";
                                                        };
                                                        _new_dst$['$inst'] = true;
                                                        if (typeof @{{instancemethod}} == "undefined") {
                                                            debugger;
                                                        }
                                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                            _new_dst$['__dict__'] = B$dict();
                                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                                        }
                                                        _new_dst$['__class__'] = @{{instancemethod}};
                                                        _new_dst$['im_class'] = value['$inst'] === true ? value['__class__'] : value;
                                                        _new_dst$['im_func'] = ga['im_func'];
                                                        _new_dst$['im_self'] = value['$inst'] === true ? value['__class__'] : value;
                                                        ga = _new_dst$;
                                                        break;
                                                    case @{{bool}}: // Some known to be non-descriptors
                                                    case @{{int}}:
                                                    case @{{long}}:
                                                    case @{{str}}:
                                                        break;
                                                    default:
                                                        // check for __get__ method in ga
                                                        if (ga['$inst'] === true) {
                                                            var get$ = @{{_getattr}}(ga, '__get__');
                                                            if (typeof get$ != 'undefined') {
                                                                ga = @{{fcall}}(this, null, get$, ga, value, value['__class__']);
                                                            }
                                                        }
                                                        break;
                                                }
                                            }
                                            @{{noraise}} = @{{AttributeError}};
                                            i = @{{fcall}}(this, null, ga, _mro$, '__int__');
                                            @{{noraise}} = _noraise$;
                                            if (i === @{{AttributeError}}) {
                                                i = [][1];
                                            }
                                            // TODO : unbind i ?
                                            break;
                                        }
                                    }
                                }
                                break;
                            default:
                                i = value['__int__'];
                                if (typeof i == "undefined" && typeof value['$dict'] != "undefined") {
                                    i = value['$dict']['__int__'];
                                }
                        }
                    if (typeof i != "undefined") {
                        return mcall(cls, null, value, '__call__');
                    }
            }
            // now we've converted numbers, so this should be a string
            if (typeof v != 'string') {
                var msg = "int() argument must be a string or a number";
                if (typeof value['__class__'] != "undefined") {
                    msg = msg + ", not '" + value['__class__']['__name__'] + "'";
                }
                @{{raise}}($new(@{{TypeError}}, B$str(msg)));
            }
            radix = 10;
        } else if (typeof v != 'string') {
            @{{raise}}($new(@{{TypeError}}, B$str("int() can't convert non-string with explicit base")));
        } else {
            if (radix.__class__ === @{{int}}) {
                radix = radix.valueOf();
            } else if (radix.__class__ === @{{bool}}) {
                radix = @{{bool}} === @{{True}} ? 1 : 0;
            } else if (radix.__class__ === @{{long}}) {
                radix = radix.valueOf();
            } else {
                @{{raise}}($new(@{{TypeError}}, B$str("an integer is required")));
            }
            if (radix < 2 || radix > 36) {
                @{{raise}}($new(@{{ValueError}}, B$str("int() base must be >= 2 and <= 36")));
            }
        }
        if (v.match($radix_regex[radix]) === null) {
            v = NaN;
        } else {
            v = v.replace(' ', '');
            v = parseInt(v, radix);
        }
        if (isNaN(v) || !isFinite(v)) {
            v = value.valueOf().replace(/^\s+/, "");
            @{{raise}}($new(@{{ValueError}}, B$str("invalid literal for int() with base " + radix + ": '" + v + "'")));
        }
        if ($min_int <= v && v <= $max_int) {
            new_int.__v = v;
            return new_int;
        }
        return @{{long}}(v);
    });

    func(m$, null, f$, '__init__', 1, ['self', 'value', 'radix'], null, null, [N$], function($self, $value, $radix) {
        return N$;
    });

    func(m$, null, f$, '__str__', 1, ['self'], null, null, null, function($self) {
        if ($self['$inst'] === true) return B$str($self.__v.toString());
        if ($self['$inst'] === false) return B$str("<type '" + $self['__name__'] + "'>");
        return B$str($self.toString());
    });

    func(m$, null, f$, '__repr__', 1, ['self'], null, null, null, function($self) {
        if ($self['$inst'] === true) return B$str($self.__v.toString());
        if ($self['$inst'] === false) return B$str("<type '" + $self['__name__'] + "'>");
        return B$str($self.toString());
    });

    func(m$, null, f$, '__nonzero__', 1, ['self'], null, null, null, function($self) {
        return __v == 0 ? @{{False}} : @{{True}};
    });

    func(m$, null, f$, '__hash__', 1, ['self'], null, null, null, function($self) {
        return '#int#' + $self.__v;
    });

    func(m$, null, f$, '__invert__', 1, ['self'], null, null, null, function($self) {
        $new(@{{int}}, ~$self.__v);
    });

    func(m$, null, f$, '__cmp__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        return $self < $y ? @{{int_minus_one}} : ($self == $y ? @{{int_zero}} : @{{int_one}});
    });

    func(m$, null, f$, '__lshift__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        if ($y < 32) {
            var v = $self.__v << $y;
            if (v > $self.__v) {
                return $new(@{{int}}, v);
            }
        }
        var v = $new(@{{long}}, $self.__v);
        return @{{long}}['$dict']['__lshift__'](v, $y);
    });

    func(m$, null, f$, '__rlshift__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        if ($self.__v < 32) {
            var v = $y << $self.__v;
            if (v > $self.__v) {
                return $new(@{{int}}, v);
            }
        }
        var v = $new(@{{long}}, $self.__v);
        return @{{long}}['$dict']['__rlshift__'](v, $y);
    });

    func(m$, null, f$, '__rshift__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        return $new(@{{int}}, $self.__v >> $y);
    });

    func(m$, null, f$, '__rrshift__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        return $new(@{{int}}, $y >> $self.__v);
    });

    func(m$, null, f$, '__and__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ == 0x02) {
            $y = $y.__v;
        } else if (!_isJsInt($y)) {
            return @{{NotImplemented}};
        }
        return $new(@{{int}}, $self.__v & $y);
    });

    func(m$, null, f$, '__rand__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ == 0x02) {
            $y = $y.__v;
        } else if (!_isJsInt($y)) {
            return @{{NotImplemented}};
        }
        return $new(@{{int}}, $y & $self.__v);
    });

    func(m$, null, f$, '__xor__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ == 0x02) {
            $y = $y.__v;
        } else if (!_isJsInt($y)) {
            return @{{NotImplemented}};
        }
        return $new(@{{int}}, $self.__v ^ $y);
    });

    func(m$, null, f$, '__rxor__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ == 0x02) {
            $y = $y.__v;
        } else if (!_isJsInt($y)) {
            return @{{NotImplemented}};
        }
        return $new(@{{int}}, $y ^ $self.__v);
    });

    func(m$, null, f$, '__or__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ == 0x02) {
            $y = $y.__v;
        } else if (!_isJsInt($y)) {
            return @{{NotImplemented}};
        }
        return $new(@{{int}}, $self.__v | $y);
    });

    func(m$, null, f$, '__ror__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ == 0x02) {
            $y = $y.__v;
        } else if (!_isJsInt($y)) {
            return @{{NotImplemented}};
        }
        return $new(@{{int}}, $y | $self.__v);
    });

    func(m$, null, f$, '__oct__', 1, ['self'], null, null, null, function($self) {
        return B$str('0x'+$self.__v.toString(8));
    });

    func(m$, null, f$, '__hex__', 1, ['self'], null, null, null, function($self) {
        return B$str('0x'+$self.__v.toString(16));
    });

    func(m$, null, f$, '__pos__', 1, ['self'], null, null, null, function($self) {
        return $self;
    });

    func(m$, null, f$, '__neg__', 1, ['self'], null, null, null, function($self) {
        return $new(@{{int}}, -$self.__v);
    });

    func(m$, null, f$, '__abs__', 1, ['self'], null, null, null, function($self) {
        if ($self.__v >= 0) return $self;
        return $new(@{{int}}, -$self.__v);
    });

    func(m$, null, f$, '__add__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        var v = $self.__v + $y;
        if ($min_int <= v && v <= $max_int) {
            return $new(@{{int}}, v);
        }
        if (-$max_float_int < v && v < $max_float_int) {
            return $new(@{{long}}, v);
        }
        var v = $new(@{{long}}, $self.__v);
        return @{{long}}['$dict']['__add__'](v, $new(@{{long}}, $y));
    });

    func(m$, null, f$, '__radd__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        var v = $self.__v + $y;
        if ($min_int <= v && v <= $max_int) {
            return $new(@{{int}}, v);
        }
        if (-$max_float_int < v && v < $max_float_int) {
            return $new(@{{long}}, v);
        }
        var v = $new(@{{long}}, $self.__v);
        return @{{long}}['$dict']['__radd__'](v, $new(@{{long}}, $y));
    });

    func(m$, null, f$, '__sub__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        var v = $self.__v - $y;
        if ($min_int <= v && v <= $max_int) {
            return $new(@{{int}}, v);
        }
        if (-$max_float_int < v && v < $max_float_int) {
            return $new(@{{long}}, v);
        }
        var v = $new(@{{long}}, $self.__v);
        return @{{long}}['$dict']['__sub__'](v, $new(@{{long}}, $y));
    });

    func(m$, null, f$, '__rsub__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        var v = $y -$self.__v;
        if ($min_int <= v && v <= $max_int) {
            return $new(@{{int}}, v);
        }
        if (-$max_float_int < v && v < $max_float_int) {
            return $new(@{{long}}, v);
        }
        var v = $new(@{{long}}, $self.__v);
        return @{{long}}['$dict']['__rsub__'](v, $new(@{{long}}, $y));
    });

    func(m$, null, f$, '__floordiv__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        if ($y == 0) @{{raise}}($new(@{{ZeroDivisionError}}, B$str("integer division or modulo b$y zero")));
        return $new(@{{int}}, Math.floor($self.__v / $y));
    });

    func(m$, null, f$, '__rfloordiv__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        if ($self.__v == 0) @{{raise}}($new(@{{ZeroDivisionError}}, B$str("integer division or modulo b$y zero")));
        return $new(@{{int}}, Math.floor($y / $self.__v));
    });

    func(m$, null, f$, '__truediv__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        if ($y == 0) @{{raise}}($new(@{{ZeroDivisionError}}, B$str("integer division or modulo b$y zero")));
        $y = $self.__v / $y
        if ($y == Math.floor($y)) {
            return $new(@{{int}}, $y);
        }
        return $new(@{{float}}, $y);
    });

    func(m$, null, f$, '__rtruediv__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        if ($self.__v == 0) @{{raise}}($new(@{{ZeroDivisionError}}, B$str("integer division or modulo b$y zero")));
        $y = $y / $self.__v
        if ($y == Math.floor($y)) {
            return $new(@{{int}}, $y);
        }
        return $new(@{{float}}, $y);
    });

    func(m$, null, f$, '__mul__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        var v = $self.__v * $y;
        if ($min_int <= v && v <= $max_int) {
            return $new(@{{int}}, v);
        }
        if (-$max_float_int < v && v < $max_float_int) {
            return $new(@{{long}}, v);
        }
        var v = $new(@{{long}}, $self.__v);
        return @{{long}}['$dict']['__mul__'](v, $new(@{{long}}, $y));
    });

    func(m$, null, f$, '__rmul__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        var v = $self.__v * $y;
        if ($min_int <= v && v <= $max_int) {
            return $new(@{{int}}, v);
        }
        if (-$max_float_int < v && v < $max_float_int) {
            return $new(@{{long}}, v);
        }
        var v = $new(@{{long}}, $self.__v);
        return @{{long}}['$dict']['__rmul__'](v, $new(@{{long}}, $y));
    });

    func(m$, null, f$, '__mod__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        if ($y == 0) @{{raise}}($new(@{{ZeroDivisionError}}, B$str("integer division or modulo b$y zero")));
        var v = $self.__v % $y;
        return $new(@{{int}}, v < 0 && $y > 0 ? v + $y : v);
    });

    func(m$, null, f$, '__rmod__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        if ($self.__v == 0) @{{raise}}($new(@{{ZeroDivisionError}}, B$str("integer division or modulo b$y zero")));
        return $new(@{{int}}, $y % $self.__v);
    });

    func(m$, null, f$, '__pow__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        if ($y.__number__ != 0x02) return @{{NotImplemented}};
        $y = $y.__v;
        var v = Math.pow($self.__v, $y);
        if ($min_int <= v && v <= $max_int) {
            return $new(@{{int}}, v);
        }
        if (-$max_float_int < v && v < $max_float_int) {
            return $new(@{{long}}, v);
        }
        var v = $new(@{{long}}, $self.__v);
        return @{{long}}['$dict']['__pow__'](v, $new(@{{long}}, $y));
    });
    """)
    __div__ = __floordiv__
    __rdiv__ = __rfloordiv__


JS("""
init_short_names$(true);
@{{int_minus_one}} = $new(@{{int}}, 100);
@{{int_zero}} = $new(@{{int}}, 100);
@{{int_one}} = $new(@{{int}}, 100);
@{{int_minus_one}}.__v = -1;
@{{int_zero}}.__v = 0;
@{{int_one}}.__v = 1;
@{{int_max_index}} = $new(@{{int}}, 2147483647);
@{{max_int}} = $new(@{{int}}, 0x7fffffff);
@{{min_int}} = $new(@{{int}}, -0x80000000);

""")


class bool(int):
    JS("""
    f$['__slots__'] = [];
    func(m$, null, f$, '__new__', 0, ['cls', 'value'], null, null, [false], function($cls, $value) {

        var v = $value.valueOf();
        switch (v) {
            case null:
            case false:
            case 0:
            case '':
                return @{{False}};
            case true:
            case 1:
                return @{{True}};
        }
        if (typeof v == 'number' || typeof v == 'string') {
            return @{{True}};
        }
        if ($value['$inst'] === true) {
            var mro$, attr, attrs = ['__nonzero__', '__len__'];
            for (var i = 0; i < attrs.length; i++) {
                attr = attrs[i];
                v = [][1];
                var mro$ = $value['__mro__'];
                var _meth_src = $value;
                switch ($value['$inst']) {
                    case true:
                        if ($value['__class__'] === @{{module}}) {
                            v = $value['$dict'][attr];
                            break;
                        } else if ($value['__class__'] === @{{function}}) {
                            switch (attr.charAt(0)) {
                                case 'i':
                                case '_':
                                    v = $value[attr];
                            }
                            break;
                        }
                        var _noraise$ = @{{noraise}};
                        var ga;
                        mro$ = $value['__class__']['__mro__'];
                        for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                            var _mro$ = mro$[mro_i$];
                            var ga = _mro$['__getattribute__'];
                            if (typeof ga == "undefined") {
                                if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                                    continue;
                                }
                                ga = _mro$['$dict']['__getattribute__'];
                            }
                            if ($value['__class__']['$inst'] === false && $value['__class__'] !== @{{module}} && typeof $value != "undefined" && typeof $value['$inst'] != "undefined") {
                                switch (ga['__class__']) {
                                    case @{{function}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = $value['$inst'] === true ? $value['__class__'] : $value;
                                        _new_dst$['im_func'] = ga;
                                        _new_dst$['im_self'] = $value['$inst'] === true ? $value : null;
                                        ga = _new_dst$;
                                        break;
                                    case @{{staticmethod}}:
                                        ga = ga['im_func'];
                                        break;
                                    case @{{classmethod}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = $value['$inst'] === true ? $value['__class__'] : $value;
                                        _new_dst$['im_func'] = ga['im_func'];
                                        _new_dst$['im_self'] = $value['$inst'] === true ? $value['__class__'] : $value;
                                        ga = _new_dst$;
                                        break;
                                    case @{{bool}}: // Some known to be non-descriptors
                                    case @{{int}}:
                                    case @{{long}}:
                                    case @{{str}}:
                                        break;
                                    default:
                                        // check for __get__ method in ga
                                        if (ga['$inst'] === true) {
                                            var get$ = @{{_getattr}}(ga, '__get__');
                                            if (typeof get$ != 'undefined') {
                                                ga = @{{fcall}}(this, null, get$, ga, $value, $value['__class__']);
                                            }
                                        }
                                        break;
                                }
                            }
                            @{{noraise}} = @{{AttributeError}};
                            v = @{{fcall}}(this, null, ga, _mro$, attr);
                            @{{noraise}} = _noraise$;
                            if (v === @{{AttributeError}}) {
                                v = [][1];
                            }
                            _meth_src = $value['__class__'];
                            $value = $value['__class__'];
                            break;
                        }
                        if (typeof v == "undefined") {
                            if (typeof $value['$dict'] != "undefined") {
                                v = $value['$dict'][attr];
                                if (typeof v != "undefined") {
                                    if (v !== {}[attr]) {
                                        break;
                                    }
                                    v = [][1];
                                }
                            }
                            switch (attr.charAt(0)) {
                                case 'i':
                                case '_':
                                    v = $value[attr];
                            }
                            if (typeof v != "undefined") {
                                break;
                            }
                        }
                    case false:
                        if (typeof v == "undefined") {
                            var _mro$, ga;
                            if ($value['$inst'] === true) {
                                _meth_src = $value['__class__'];
                            } else {
                                switch (attr.charAt(0)) {
                                    case 'i':
                                    case '_':
                                        v = $value[attr];
                                }
                                if (typeof v != "undefined") {
                                    break;
                                }

                            }
                            if (typeof v == "undefined") {
                                for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                                    _mro$ = mro$[mro_i$];
                                    v = _mro$['$dict'][attr];
                                    if (typeof v != "undefined") {
                                        if (v !== {}[attr]) {
                                            break;
                                        }
                                        v = [][1];
                                    }
                                    switch (attr.charAt(0)) {
                                        case 'i':
                                        case '_':
                                            v = _mro$[attr];
                                    }
                                    if (typeof v != "undefined") {
                                        break;
                                    }
                                }
                            }
                            if (typeof v == "undefined" && attr !== '__get__') {
                                for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                                    _mro$ = mro$[mro_i$];
                                    if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                        continue;
                                    }
                                    ga = _mro$['$dict']['__getattr__'];
                                    if ($value['__class__']['$inst'] === false && $value['__class__'] !== @{{module}} && typeof $value != "undefined" && typeof $value['$inst'] != "undefined") {
                                        switch (ga['__class__']) {
                                            case @{{function}}:
                                                var _new_dst$ = function ( ) {
                                                    var args = Array.prototype.slice.call(arguments);
                                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                        if (arguments.callee['im_self'] !== null) {
                                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                        }
                                                    }
                                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                                    if (typeof a == "undefined") {
                                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                    }
                                                    if (args.length >= 3) {
                                                        var len = args.length;
                                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                        }
                                                    }
                                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                                _new_dst$['toString'] = function ( ) {
                                                    try {
                                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                    } catch (e) {
                                                    }
                                                    try {
                                                        return "<" + this.__class__.__name__ + " instance>";
                                                    } catch (e) {
                                                    }
                                                    return "<instance>";
                                                };
                                                _new_dst$['$inst'] = true;
                                                if (typeof @{{instancemethod}} == "undefined") {
                                                    debugger;
                                                }
                                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                    _new_dst$['__dict__'] = B$dict();
                                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                                }
                                                _new_dst$['__class__'] = @{{instancemethod}};
                                                _new_dst$['im_class'] = $value['$inst'] === true ? $value['__class__'] : $value;
                                                _new_dst$['im_func'] = ga;
                                                _new_dst$['im_self'] = $value['$inst'] === true ? $value : null;
                                                ga = _new_dst$;
                                                break;
                                            case @{{staticmethod}}:
                                                ga = ga['im_func'];
                                                break;
                                            case @{{classmethod}}:
                                                var _new_dst$ = function ( ) {
                                                    var args = Array.prototype.slice.call(arguments);
                                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                        if (arguments.callee['im_self'] !== null) {
                                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                        }
                                                    }
                                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                                    if (typeof a == "undefined") {
                                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                    }
                                                    if (args.length >= 3) {
                                                        var len = args.length;
                                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                        }
                                                    }
                                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                                _new_dst$['toString'] = function ( ) {
                                                    try {
                                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                    } catch (e) {
                                                    }
                                                    try {
                                                        return "<" + this.__class__.__name__ + " instance>";
                                                    } catch (e) {
                                                    }
                                                    return "<instance>";
                                                };
                                                _new_dst$['$inst'] = true;
                                                if (typeof @{{instancemethod}} == "undefined") {
                                                    debugger;
                                                }
                                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                    _new_dst$['__dict__'] = B$dict();
                                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                                }
                                                _new_dst$['__class__'] = @{{instancemethod}};
                                                _new_dst$['im_class'] = $value['$inst'] === true ? $value['__class__'] : $value;
                                                _new_dst$['im_func'] = ga['im_func'];
                                                _new_dst$['im_self'] = $value['$inst'] === true ? $value['__class__'] : $value;
                                                ga = _new_dst$;
                                                break;
                                            case @{{bool}}: // Some known to be non-descriptors
                                            case @{{int}}:
                                            case @{{long}}:
                                            case @{{str}}:
                                                break;
                                            default:
                                                // check for __get__ method in ga
                                                if (ga['$inst'] === true) {
                                                    var get$ = @{{_getattr}}(ga, '__get__');
                                                    if (typeof get$ != 'undefined') {
                                                        ga = @{{fcall}}(this, null, get$, ga, $value, $value['__class__']);
                                                    }
                                                }
                                                break;
                                        }
                                    }
                                    @{{noraise}} = @{{AttributeError}};
                                    v = @{{fcall}}(this, null, ga, _mro$, attr);
                                    @{{noraise}} = _noraise$;
                                    if (v === @{{AttributeError}}) {
                                        v = [][1];
                                    }
                                    // TODO : unbind v ?
                                    break;
                                }
                            }
                        }
                        break;
                    default:
                        v = $value[attr];
                        if (typeof v == "undefined" && typeof $value['$dict'] != "undefined") {
                            v = $value['$dict'][attr];
                        }
                }
                if (typeof v != "undefined") {
                    if (_meth_src['$inst'] === false && $value['__class__'] !== @{{module}} && typeof v != "undefined" && typeof v['$inst'] != "undefined") {
                        switch (v['__class__']) {
                            case @{{function}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = $value['$inst'] === true ? $value['__class__'] : $value;
                                _new_dst$['im_func'] = v;
                                _new_dst$['im_self'] = $value['$inst'] === true ? $value : null;
                                v = _new_dst$;
                                break;
                            case @{{staticmethod}}:
                                v = v['im_func'];
                                break;
                            case @{{classmethod}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = $value['$inst'] === true ? $value['__class__'] : $value;
                                _new_dst$['im_func'] = v['im_func'];
                                _new_dst$['im_self'] = $value['$inst'] === true ? $value['__class__'] : $value;
                                v = _new_dst$;
                                break;
                            case @{{bool}}: // Some known to be non-descriptors
                            case @{{int}}:
                            case @{{long}}:
                            case @{{str}}:
                                break;
                            default:
                                // check for __get__ method in v
                                if (v['$inst'] === true) {
                                    var get$ = @{{_getattr}}(v, '__get__');
                                    if (typeof get$ != 'undefined') {
                                        v = @{{fcall}}(this, null, get$, v, $value, $value['__class__']);
                                    }
                                }
                                break;
                        }
                    }
                    v = @{{fcall}}(this, null, v, $value);
                    switch (attr) {
                        case '__nonzero__':
                            return v.__v ? @{{True}} : @{{False}};
                        case '__len__':
                            return v.__v != 0 ? @{{True}} : @{{False}};
                    }
                }
            }
        }
        return @{{True}};
    });""")

    def __init__(self, value):
        pass

    def __str__(self):
        if self is True:
            return "True"
        if self is False:
            return "False"
        if JS("@{{self}}.$inst === true"):
            if JS("@{{self}}.__v"):
                return "True"
            else:
                return "False"
        JS("""if (@{{self}}.$inst === false) return B$str("<type '" + @{{self}}.__name__ + "'>");
        return B$str(@{{self}}.toString());""")

    __repr__ = __str__

JS("init_short_names$(true);")
JS("""
@{{False}} = $new(@{{int}}, 100);
@{{True}} = $new(@{{int}}, 100);
@{{False}}.__class__ = @{{bool}};
@{{True}}.__class__ = @{{bool}};
@{{False}}.__v = 0;
@{{True}}.__v = 1;
@{{False}}['toString'] = function () {return 'False'};
@{{True}}['toString'] = function () {return 'True'};
""")
JS("init_short_names$(true);")


class long(object):
    pass
# This is the python long implementation. See:
#  - Include/longintrepr.h
#  - Include/longobject.h
#  - Objects/longobject.c
JS("""
(function() {

    var $log2 = Math.log(2);
    var $DigitValue = [
            37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
            37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
            37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
            0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  37, 37, 37, 37, 37, 37,
            37, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
            25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 37, 37, 37, 37,
            37, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
            25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 37, 37, 37, 37,
            37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
            37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
            37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
            37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
            37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
            37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
            37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
            37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37
    ];
    var $log_base_PyLong_BASE = new Array();
    var $convwidth_base = new Array();
    var $convmultmax_base = new Array();
    for (var i = 0; i < 37; i++) {
        $log_base_PyLong_BASE[i] = $convwidth_base[i] = $convmultmax_base[i] = 0;
    }
    var $cdigit = '0123456789abcdefghijklmnopqrstuvwxyz';


    var PyLong_SHIFT = 15;
    var PyLong_MASK = 0x7fff;
    var PyLong_BASE = 0x8000;

    var KARATSUBA_CUTOFF = 70;
    var KARATSUBA_SQUARE_CUTOFF = (2 * KARATSUBA_CUTOFF);

    var FIVEARY_CUTOFF = 8;

    function array_eq(a, b, n) {
        for (var i = 0 ; i < n; i++) {
            if (a[i] != b[i])
                return false;
        }
        return true;
    }

    function long_normalize(v) {
        var j = v.ob_size < 0 ? -v.ob_size:v.ob_size;
        var i = j;
        while (i > 0 && v.ob_digit[i-1] == 0) {
            i--;
        }
        if (i != j) {
            v.ob_size = v.ob_size < 0 ? -i:i;
        }
        return v;
    }

    function AsScaledDouble(vv) {
        var multiplier = PyLong_BASE; // 1L << PyLong_SHIFT == 1 << 15
        var neg, i, x, nbitsneeded;

        if (vv.ob_size < 0) {
            i = -vv.ob_size;
            neg = true;
        } else if (vv.ob_size > 0) {
            i = vv.ob_size;
            neg = false;
        } else {
            return [0.0, 0];
        }
        --i;
        x = vv.ob_digit[i];
        nbitsneeded = 56;
        while (i > 0 && nbitsneeded > 0) {
            --i;
            x = x * multiplier + vv.ob_digit[i];
            nbitsneeded -= PyLong_SHIFT;
        }
        if (neg) {
            return [-x, i];
        }
        return [x, i];
    }

    function v_iadd(x, m, y, n) {
        var i, carry = 0;
        for (i = 0; i < n; ++i) {
                carry += x[i] + y[i];
                x[i] = carry & PyLong_MASK;
                carry >>= PyLong_SHIFT;
        }
        for (; carry && i < m; ++i) {
                carry += x[i];
                x[i] = carry & PyLong_MASK;
                carry >>= PyLong_SHIFT;
        }
        return carry;
    }

    function v_isub(x, m, y, n) {
        var i, borrow = 0;
        for (i = 0; i < n; ++i) {
                borrow = x[i] - y[i] - borrow;
                x[i] = borrow & PyLong_MASK;
                borrow >>= PyLong_SHIFT;
                borrow &= 1;
        }
        for (; borrow && i < m; ++i) {
                borrow = x[i] - borrow;
                x[i] = borrow & PyLong_MASK;
                borrow >>= PyLong_SHIFT;
                borrow &= 1;
        }
        return borrow;
    }

    //function mul1(a, n) {
    //    return muladd1(a, n, 0);
    //}

    function muladd1(z, a, n, extra) {
        var size_a = a.ob_size < 0 ? -a.ob_size : a.ob_size;
        var carry = extra, i;

        for (i = 0; i < size_a; ++i) {
                carry += a.ob_digit[i] * n;
                z.ob_digit[i] = carry & PyLong_MASK;
                carry >>= PyLong_SHIFT;
        }
        z.ob_digit[i] = carry;
        z.ob_size = i + 1;
        return long_normalize(z);
    }

    function inplace_divrem1(pout, pin, pout_idx, pin_idx, size, n) {
        var rem = 0, hi = 0;
        pin_idx += size;
        pout_idx += size;
        while (pin_idx > pin.length) {
            --size;
            --pin_idx;
            pout[--pout_idx] = 0;
        }
        while (--size >= 0) {
            rem = (rem << PyLong_SHIFT) + pin[--pin_idx];
            pout[--pout_idx] = hi = Math.floor(rem / n);
            rem -= hi * n;
        }
        return [rem, pout_idx, pin_idx];
    }

    function divrem1(a, n, prem) {
        var size = a.ob_size < 0 ? -a.ob_size : a.ob_size;
        var z = $new(@{{long}}, 0);

        prem[0] = inplace_divrem1(z.ob_digit, a.ob_digit, 0, 0, size, n)[0];
        z.ob_size = size;
        return long_normalize(z);
    }

    function Format(aa, base, addL, newstyle, noBase) {
        var text, str, p, i, bits, sz, rem, sign = '';
        var c_0 = "0".charCodeAt(0);
        var c_a = "a".charCodeAt(0);
        base = base.valueOf();

        if (aa.ob_size == 0) {
            if (addL) {
                text = "0L";
            } else {
                text = "0";
            }
        } else {
            if (aa.ob_size < 0) {
                sign = '-';
                size_a = -aa.ob_size;
            } else {
                size_a = aa.ob_size;
            }
            i = base;
            bits = 0;
            while (i > 1) {
                ++bits;
                i >>>= 1;
            }
            i = addL ? 6 : 5;
            j = size_a * PyLong_SHIFT + bits - 1;
            sz = Math.floor(i + j / bits);
            if (j / PyLong_SHIFT < size_a || sz < i) {
                @{{raise}}($new(@{{OverflowError}}, B$str("long is too large to format")));
            }
            str = new Array();
            p = sz;
            if (addL) str[--p] = 'L';
            if ((base & (base - 1)) == 0) {
                var accum = 0, accumbits = 0, basebits = 1;
                i = base;
                while ((i >>>= 1) > 1) ++basebits;
                for (i = 0; i < size_a; ++i) {
                    accum |= aa.ob_digit[i] << accumbits;
                    accumbits += PyLong_SHIFT;
                    while (1) {
                        var cdigit = accum & (base - 1);
                        str[--p] = $cdigit.charAt(cdigit);
                        accumbits -= basebits;
                        accum >>>= basebits;
                        if (i < size_a-1) {
                            if (accumbits < basebits) break;
                        } else if (accum <= 0) break;
                    }
                }
                text = str.join("");
            } else {
                // Not 0, and base not a power of 2.
                var scratch, pin, scratch_idx, pin_idx;
                var powbase = base, power = 1, size = size_a;

                while (1) {
                    var newpow = powbase * base;
                    if (newpow >>> PyLong_SHIFT)  /* doesn't fit in a digit */
                        break;
                    powbase = newpow;
                    ++power;
                }
                scratch = aa.ob_digit.slice(0);
                pin = aa.ob_digit;
                scratch_idx = pin_idx = 0;
                do {
                        var ntostore = power;
                        rem = inplace_divrem1(scratch, pin, scratch_idx, pin_idx, size, powbase);
                        scratch_idx = rem[1];
                        rem = rem[0];
                        pin = scratch;
                        pin_idx = 0;
                        if (pin[size - 1] == 0) {
                            --size;
                        }
                        do {
                            var nextrem = Math.floor(rem / base);
                            str[--p] = $cdigit.charAt(rem - nextrem * base);
                            rem = nextrem;
                            --ntostore;
                        } while (ntostore && (size || rem));
                } while (size !=0);
                text = str.slice(p).join("");
            }
            text = text.replace(/^\s+/, ""); // lstrip
            if (text == "" || text == "L") text = "0" + text;
        }
        if (noBase !== false) {
            switch (base) {
                case 10:
                    break;
                case 2:
                    text = '0b' + text;
                    break;
                case 8:
                    text = (newstyle ? '0o':(aa.ob_size ? '0': '')) + text;
                    break;
                case 16:
                    text = '0x' + text;
                    break;
                default:
                    text = base + '#' + text;
                    break;
            }
        }
        return sign + text;
    }

    function long_divrem(a, b, pdiv, prem) {
        var size_a = a.ob_size < 0 ? -a.ob_size : a.ob_size;
        var size_b = b.ob_size < 0 ? -b.ob_size : b.ob_size;
        var z = null;

        if (size_b == 0) {
            @{{raise}}($new(@{{ZeroDivisionError}}, B$str("long division or modulo by zero")));
        }
        if (size_a < size_b ||
            (size_a == size_b &&
             a.ob_digit[size_a-1] < b.ob_digit[size_b-1])) {
                // |a| < |b|
                pdiv.ob_size = 0;
                prem.ob_digit = a.ob_digit.slice(0);
                prem.ob_size = a.ob_size;
                return 0;
        }
        if (size_b == 1) {
                rem = [0];
                prem.ob_digit = [0];
                prem.ob_size = 1;
                z = divrem1(a, b.ob_digit[0], prem.ob_digit);
                prem = long_normalize(prem);
        }
        else {
                z = @{{!x_divrem}}(a, b, prem);
        }
        if (z === null) {
            pdiv.ob_size = 0;
        } else {
            pdiv.ob_digit = z.ob_digit.slice(0);
            pdiv.ob_size = z.ob_size;
        }
        if ((a.ob_size < 0) != (b.ob_size < 0))
                pdiv.ob_size = -(pdiv.ob_size);
        if (a.ob_size < 0 && prem.ob_size != 0)
                prem.ob_size = -prem.ob_size;
        return 0;
    }

    function x_divrem(v1, w1, prem) {
        var size_w = w1.ob_size < 0 ? -w1.ob_size : w1.ob_size;
        var d = Math.floor(PyLong_BASE / (w1.ob_digit[size_w-1] + 1));
        var v = muladd1($x_divrem_v, v1, d, 0);
        var w = muladd1($x_divrem_w, w1, d, 0);
        var a, j, k;
        var size_v = v.ob_size < 0 ? -v.ob_size : v.ob_size;
        k = size_v - size_w;
        a = $new(@{{long}}, 0);
        a.ob_size = k + 1;

        for (j = size_v; k >= 0; --j, --k) {
            var vj = (j >= size_v) ? 0 : v.ob_digit[j];
            var carry = 0;
            var q, i;

            if (vj == w.ob_digit[size_w-1])
                q = PyLong_MASK;
            else
                q = Math.floor(((vj << PyLong_SHIFT) + v.ob_digit[j-1]) /
                        w.ob_digit[size_w-1]);

            while (w.ob_digit[size_w-2]*q >
                    ((
                        (vj << PyLong_SHIFT)
                        + v.ob_digit[j-1]
                        - q*w.ob_digit[size_w-1]
                                                ) << PyLong_SHIFT)
                    + v.ob_digit[j-2])
                --q;

            for (i = 0; i < size_w && i+k < size_v; ++i) {
                var z = w.ob_digit[i] * q;
                var zz = z >>> PyLong_SHIFT;
                carry += v.ob_digit[i+k] - z
                        + (zz << PyLong_SHIFT);
                v.ob_digit[i+k] = carry & PyLong_MASK;
                // carry = Py_ARITHMETIC_RIGHT_SHIFT(BASE_TWODIGITS_TYPE, carry, PyLong_SHIFT);
                carry >>= PyLong_SHIFT;
                carry -= zz;
            }

            if (i+k < size_v) {
                carry += v.ob_digit[i+k];
                v.ob_digit[i+k] = 0;
            }

            if (carry == 0)
                a.ob_digit[k] = q;
            else {
                a.ob_digit[k] = q-1;
                carry = 0;
                for (i = 0; i < size_w && i+k < size_v; ++i) {
                    carry += v.ob_digit[i+k] + w.ob_digit[i];
                    v.ob_digit[i+k] = carry & PyLong_MASK;
                    // carry = Py_ARITHMETIC_RIGHT_SHIFT( BASE_TWODIGITS_TYPE, carry, PyLong_SHIFT);
                    carry >>= PyLong_SHIFT;
                }
            }
        } /* for j, k */

        i = divrem1(v, d, prem);
        prem.ob_digit = i.ob_digit.slice(0);
        prem.ob_size = i.ob_size;
        return long_normalize(a);
    }

    function x_add(a, b) {
        var size_a = a.ob_size < 0 ? -a.ob_size : a.ob_size;
        var size_b = b.ob_size < 0 ? -b.ob_size : b.ob_size;
        var z = $new(@{{long}}, 0);
        var i;
        var carry = 0;

        if (size_a < size_b) {
            var temp = a;
            a = b;
            b = temp;
            temp = size_a;
            size_a = size_b;
            size_b = temp;
        }
        for (i = 0; i < size_b; ++i) {
                carry += a.ob_digit[i] + b.ob_digit[i];
                z.ob_digit[i] = carry & PyLong_MASK;
                carry >>>= PyLong_SHIFT;
        }
        for (; i < size_a; ++i) {
                carry += a.ob_digit[i];
                z.ob_digit[i] = carry & PyLong_MASK;
                carry >>>= PyLong_SHIFT;
        }
        z.ob_digit[i] = carry;
        z.ob_size = i+1;
        return long_normalize(z);
    }

    function x_sub(a, b) {
        var size_a = a.ob_size < 0 ? -a.ob_size : a.ob_size;
        var size_b = b.ob_size < 0 ? -b.ob_size : b.ob_size;
        var z = $new(@{{long}}, 0);
        var i;
        var borrow = 0;
        var sign = 1;

        if (size_a < size_b) {
            var temp = a;
            a = b;
            b = temp;
            temp = size_a;
            size_a = size_b;
            size_b = temp;
            sign = -1;
        } else if (size_a == size_b) {
            i = size_a;
            while (--i >= 0 && a.ob_digit[i] == b.ob_digit[i])
                ;
            if (i < 0)
                return z;
            if (a.ob_digit[i] < b.ob_digit[i]) {
                var temp = a;
                a = b;
                b = temp;
                temp = size_a;
                size_a = size_b;
                size_b = temp;
                sign = -1;
            }
            size_a = size_b = i+1;
        }
        for (i = 0; i < size_b; ++i) {
                borrow = a.ob_digit[i] - b.ob_digit[i] - borrow;
                z.ob_digit[i] = borrow & PyLong_MASK;
                borrow >>>= PyLong_SHIFT;
                borrow &= 1;
        }
        for (; i < size_a; ++i) {
                borrow = a.ob_digit[i] - borrow;
                z.ob_digit[i] = borrow & PyLong_MASK;
                borrow >>>= PyLong_SHIFT;
                borrow &= 1;
        }
        z.ob_size = i;
        if (sign < 0)
            z.ob_size = -(z.ob_size);
        return long_normalize(z);
    }

    function x_mul(a, b) {
        var size_a = a.ob_size < 0 ? -a.ob_size : a.ob_size;
        var size_b = b.ob_size < 0 ? -b.ob_size : b.ob_size;
        var z = $new(@{{long}}, 0);
        var i, s;

        z.ob_size = size_a + size_b;
        for (i = 0; i < z.ob_size; i++) {
            z.ob_digit[i] = 0;
        }
        if (size_a == size_b && array_eq(a.ob_digit, b.ob_digit, size_a)) {
            // Efficient squaring per HAC, Algorithm 14.16:
            for (i = 0; i < size_a; ++i) {
                var carry;
                var f = a.ob_digit[i];
                var pz = (i << 1);
                var pa = i + 1;
                var paend = size_a;

                carry = z.ob_digit[pz] + f * f;
                z.ob_digit[pz++] = carry & PyLong_MASK;
                carry >>>= PyLong_SHIFT;

                f <<= 1;
                while (pa < paend) {
                    carry += z.ob_digit[pz] + a.ob_digit[pa++] * f;
                    z.ob_digit[pz++] = carry & PyLong_MASK;
                    carry >>>= PyLong_SHIFT;
                }
                if (carry) {
                    carry += z.ob_digit[pz];
                    z.ob_digit[pz++] = carry & PyLong_MASK;
                    carry >>>= PyLong_SHIFT;
                }
                if (carry) {
                    z.ob_digit[pz] += carry & PyLong_MASK;
                }
            }
        }
        else {  // a is not the same as b -- gradeschool long mult
            for (i = 0; i < size_a; ++i) {
                var carry = 0;
                var f = a.ob_digit[i];
                var pz = i;
                var pb = 0;
                var pbend = size_b;

                while (pb < pbend) {
                    carry += z.ob_digit[pz] + b.ob_digit[pb++] * f;
                    z.ob_digit[pz++] = carry & PyLong_MASK;
                    carry >>>= PyLong_SHIFT;
                }
                if (carry) {
                    z.ob_digit[pz] += carry & PyLong_MASK;
                }
            }
        }
        z.ob_size = z.ob_digit.length;
        return long_normalize(z);
    }

    function l_divmod(v, w, pdiv, pmod) {
        var div = $l_divmod_div,
            mod = $l_divmod_mod;

        if (long_divrem(v, w, div, mod) < 0)
                return -1;
        if (pdiv == null && pmod == null) return 0;

        if ((mod.ob_size < 0 && w.ob_size > 0) ||
            (mod.ob_size > 0 && w.ob_size < 0)) {
                mod = @{{long}}['$dict']['__add__'](mod, w);
                div = @{{long}}['$dict']['__sub__'](div, $const_long_1);
        }
        if (pdiv !== null) {
            pdiv.ob_digit = div.ob_digit.slice(0);
            pdiv.ob_size = div.ob_size;
        }
        if (pmod !== null) {
            pmod.ob_digit = mod.ob_digit.slice(0);
            pmod.ob_size = mod.ob_size;
        }
        return 0;
    }


    // class long

    var f$ = @{{long}};
    f$['__slots__'] = [];

    func(m$, null, f$, '__new__', 0, ['cls', 'value', 'radix'], null, null, [null], function(cls, value, radix) {
        var v = value.valueOf(), i;
        var new_long = B$__new__(@{{long}});
        new_long['__number__'] = 0x04;
        new_long['valueOf'] = function() {
                var x, v;
                x = AsScaledDouble(this);
                // ldexp(a,b) == a * (2**b)
                v = x[0] * Math.pow(2.0, x[1] * PyLong_SHIFT);
                return v;
            };
        new_long['toString'] = function() {return this['__class__']['$dict']['__str__'](this)};
        if (!radix || radix.valueOf() == 0) {
            if (typeof value == "undefined") {
               @{{raise}}($new(@{{TypeError}}, B$str("long() takes at least 1 argument")));
            }
            // handle some javascript types
            switch (typeof value) {
                case 'number':
                    v = v > 0 ? Math.floor(v) : Math.ceil(v);
                    break;
                case 'string':
                    break;
                case 'boolean':
                    return v ? @{{long_one}} : @{{long_zero}};
                case "undefined":
                    @{{raise}}($new(@{{TypeError}}, B$str("long() takes at least 1 argument")));
                default:
                // TODO: change usage of value.__number__
                // to value.__class__
                switch (value.__number__) {
                    case 0x01: // float
                        v = v > 0 ? Math.floor(v) : Math.ceil(v);
                        break;
                    case 0x02: // int
                        break;
                    case 0x04: // long
                        return value;
                    default:
                        if (v === 'true') {
                            return @{{long_one}};
                        } else if (v === 'true') {
                            return @{{long_zero}};
                        }
/*
                        // check whether we've got an object that has its own __long__() method
                        var mro$;
                            i = [][1];
                            var mro$ = value['__mro__'];
                            var _meth_src = value;
                            switch (value['$inst']) {
                                case true:
                                    if (value['__class__'] === @{{module}}) {
                                        i = value['$dict']['__long__'];
                                        break;
                                    } else if (value['__class__'] === @{{function}}) {
                                        switch ('__long__'.charAt(0)) {
                                            case 'i':
                                            case '_':
                                                i = value['__long__'];
                                        }
                                        break;
                                    }
                                    var _noraise$ = @{{noraise}};
                                    var ga;
                                    mro$ = value['__class__']['__mro__'];
                                    for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                                        var _mro$ = mro$[mro_i$];
                                        var ga = _mro$['__getattribute__'];
                                        if (typeof ga == "undefined") {
                                            if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                                                continue;
                                            }
                                            ga = _mro$['$dict']['__getattribute__'];
                                        }
                                        if (value['__class__']['$inst'] === false && value['__class__'] !== @{{module}} && typeof value != "undefined" && typeof value['$inst'] != "undefined") {
                                            switch (ga['__class__']) {
                                                case @{{function}}:
                                                    var _new_dst$ = function ( ) {
                                                        var args = Array.prototype.slice.call(arguments);
                                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                            if (arguments.callee['im_self'] !== null) {
                                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                            }
                                                        }
                                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                                        if (typeof a == "undefined") {
                                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                        }
                                                        if (args.length >= 3) {
                                                            var len = args.length;
                                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                            }
                                                        }
                                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                    }
                                                    _new_dst$['toString'] = function ( ) {
                                                        try {
                                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                        } catch (e) {
                                                        }
                                                        try {
                                                            return "<" + this.__class__.__name__ + " instance>";
                                                        } catch (e) {
                                                        }
                                                        return "<instance>";
                                                    };
                                                    _new_dst$['$inst'] = true;
                                                    if (typeof @{{instancemethod}} == "undefined") {
                                                        debugger;
                                                    }
                                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                        _new_dst$['__dict__'] = B$dict();
                                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                                    }
                                                    _new_dst$['__class__'] = @{{instancemethod}};
                                                    _new_dst$['im_class'] = value['$inst'] === true ? value['__class__'] : value;
                                                    _new_dst$['im_func'] = ga;
                                                    _new_dst$['im_self'] = value['$inst'] === true ? value : null;
                                                    ga = _new_dst$;
                                                    break;
                                                case @{{staticmethod}}:
                                                    ga = ga['im_func'];
                                                    break;
                                                case @{{classmethod}}:
                                                    var _new_dst$ = function ( ) {
                                                        var args = Array.prototype.slice.call(arguments);
                                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                            if (arguments.callee['im_self'] !== null) {
                                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                            }
                                                        }
                                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                                        if (typeof a == "undefined") {
                                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                        }
                                                        if (args.length >= 3) {
                                                            var len = args.length;
                                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                            }
                                                        }
                                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                    }
                                                    _new_dst$['toString'] = function ( ) {
                                                        try {
                                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                        } catch (e) {
                                                        }
                                                        try {
                                                            return "<" + this.__class__.__name__ + " instance>";
                                                        } catch (e) {
                                                        }
                                                        return "<instance>";
                                                    };
                                                    _new_dst$['$inst'] = true;
                                                    if (typeof @{{instancemethod}} == "undefined") {
                                                        debugger;
                                                    }
                                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                        _new_dst$['__dict__'] = B$dict();
                                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                                    }
                                                    _new_dst$['__class__'] = @{{instancemethod}};
                                                    _new_dst$['im_class'] = value['$inst'] === true ? value['__class__'] : value;
                                                    _new_dst$['im_func'] = ga['im_func'];
                                                    _new_dst$['im_self'] = value['$inst'] === true ? value['__class__'] : value;
                                                    ga = _new_dst$;
                                                    break;
                                                case @{{bool}}: // Some known to be non-descriptors
                                                case @{{int}}:
                                                case @{{long}}:
                                                case @{{str}}:
                                                    break;
                                                default:
                                                    // check for __get__ method in ga
                                                    if (ga['$inst'] === true) {
                                                        var get$ = @{{_getattr}}(ga, '__get__');
                                                        if (typeof get$ != 'undefined') {
                                                            ga = @{{fcall}}(this, null, get$, ga, value, value['__class__']);
                                                        }
                                                    }
                                                    break;
                                            }
                                        }
                                        @{{noraise}} = @{{AttributeError}};
                                        i = @{{fcall}}(this, null, ga, _mro$, '__long__');
                                        @{{noraise}} = _noraise$;
                                        if (i === @{{AttributeError}}) {
                                            i = [][1];
                                        }
                                        _meth_src = value['__class__'];
                                        value = value['__class__'];
                                        break;
                                    }
                                    if (typeof i == "undefined") {
                                        if (typeof value['$dict'] != "undefined") {
                                            i = value['$dict']['__long__'];
                                            if (typeof i != "undefined") {
                                                if (i !== {}['__long__']) {
                                                    break;
                                                }
                                                i = [][1];
                                            }
                                        }
                                        switch ('__long__'.charAt(0)) {
                                            case 'i':
                                            case '_':
                                                i = value['__long__'];
                                        }
                                        if (typeof i != "undefined") {
                                            break;
                                        }
                                    }
                                case false:
                                    if (typeof i == "undefined") {
                                        var _mro$, ga;
                                        if (value['$inst'] === true) {
                                            _meth_src = value['__class__'];
                                        } else {
                                            switch ('__long__'.charAt(0)) {
                                                case 'i':
                                                case '_':
                                                    i = value['__long__'];
                                            }
                                            if (typeof i != "undefined") {
                                                break;
                                            }

                                        }
                                        if (typeof i == "undefined") {
                                            for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                                                _mro$ = mro$[mro_i$];
                                                i = _mro$['$dict']['__long__'];
                                                if (typeof i != "undefined") {
                                                    if (i !== {}['__long__']) {
                                                        break;
                                                    }
                                                    i = [][1];
                                                }
                                                switch ('__long__'.charAt(0)) {
                                                    case 'i':
                                                    case '_':
                                                        i = _mro$['__long__'];
                                                }
                                                if (typeof i != "undefined") {
                                                    break;
                                                }
                                            }
                                        }
                                        if (typeof i == "undefined" && '__long__' !== '__get__') {
                                            for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                                                _mro$ = mro$[mro_i$];
                                                if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                                    continue;
                                                }
                                                ga = _mro$['$dict']['__getattr__'];
                                                if (value['__class__']['$inst'] === false && value['__class__'] !== @{{module}} && typeof value != "undefined" && typeof value['$inst'] != "undefined") {
                                                    switch (ga['__class__']) {
                                                        case @{{function}}:
                                                            var _new_dst$ = function ( ) {
                                                                var args = Array.prototype.slice.call(arguments);
                                                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                                    if (arguments.callee['im_self'] !== null) {
                                                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                                    }
                                                                }
                                                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                                                if (typeof a == "undefined") {
                                                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                                }
                                                                if (args.length >= 3) {
                                                                    var len = args.length;
                                                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                                    }
                                                                }
                                                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                            }
                                                            _new_dst$['toString'] = function ( ) {
                                                                try {
                                                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                                } catch (e) {
                                                                }
                                                                try {
                                                                    return "<" + this.__class__.__name__ + " instance>";
                                                                } catch (e) {
                                                                }
                                                                return "<instance>";
                                                            };
                                                            _new_dst$['$inst'] = true;
                                                            if (typeof @{{instancemethod}} == "undefined") {
                                                                debugger;
                                                            }
                                                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                                _new_dst$['__dict__'] = B$dict();
                                                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                                            }
                                                            _new_dst$['__class__'] = @{{instancemethod}};
                                                            _new_dst$['im_class'] = value['$inst'] === true ? value['__class__'] : value;
                                                            _new_dst$['im_func'] = ga;
                                                            _new_dst$['im_self'] = value['$inst'] === true ? value : null;
                                                            ga = _new_dst$;
                                                            break;
                                                        case @{{staticmethod}}:
                                                            ga = ga['im_func'];
                                                            break;
                                                        case @{{classmethod}}:
                                                            var _new_dst$ = function ( ) {
                                                                var args = Array.prototype.slice.call(arguments);
                                                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                                    if (arguments.callee['im_self'] !== null) {
                                                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                                    }
                                                                }
                                                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                                                if (typeof a == "undefined") {
                                                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                                }
                                                                if (args.length >= 3) {
                                                                    var len = args.length;
                                                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                                    }
                                                                }
                                                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                            }
                                                            _new_dst$['toString'] = function ( ) {
                                                                try {
                                                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                                } catch (e) {
                                                                }
                                                                try {
                                                                    return "<" + this.__class__.__name__ + " instance>";
                                                                } catch (e) {
                                                                }
                                                                return "<instance>";
                                                            };
                                                            _new_dst$['$inst'] = true;
                                                            if (typeof @{{instancemethod}} == "undefined") {
                                                                debugger;
                                                            }
                                                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                                _new_dst$['__dict__'] = B$dict();
                                                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                                            }
                                                            _new_dst$['__class__'] = @{{instancemethod}};
                                                            _new_dst$['im_class'] = value['$inst'] === true ? value['__class__'] : value;
                                                            _new_dst$['im_func'] = ga['im_func'];
                                                            _new_dst$['im_self'] = value['$inst'] === true ? value['__class__'] : value;
                                                            ga = _new_dst$;
                                                            break;
                                                        case @{{bool}}: // Some known to be non-descriptors
                                                        case @{{int}}:
                                                        case @{{long}}:
                                                        case @{{str}}:
                                                            break;
                                                        default:
                                                            // check for __get__ method in ga
                                                            if (ga['$inst'] === true) {
                                                                var get$ = @{{_getattr}}(ga, '__get__');
                                                                if (typeof get$ != 'undefined') {
                                                                    ga = @{{fcall}}(this, null, get$, ga, value, value['__class__']);
                                                                }
                                                            }
                                                            break;
                                                    }
                                                }
                                                @{{noraise}} = @{{AttributeError}};
                                                i = @{{fcall}}(this, null, ga, _mro$, '__long__');
                                                @{{noraise}} = _noraise$;
                                                if (i === @{{AttributeError}}) {
                                                    i = [][1];
                                                }
                                                // TODO : unbind i ?
                                                break;
                                            }
                                        }
                                    }
                                    break;
                                default:
                                    i = value['__long__'];
                                    if (typeof i == "undefined" && typeof value['$dict'] != "undefined") {
                                        i = value['$dict']['__long__'];
                                    }
                            }
                        if (typeof i != "undefined") {
                            return mcall(cls, null, value, '__call__');
                        }
*/
                }
            }
            radix = null;
        }

        new_long.ob_size = 0;
        new_long.ob_digit = new Array();
        if (typeof v == 'number') {
            if (radix) {
                @{{raise}}($new(@{{TypeError}}, B$str("long() can't convert non-string with explicit base")));
            }
            if ($min_int <= v && v <= $max_int) {
                var neg = false;
                var ndig = 0;

                if (v < 0) {
                    v = -v;
                    neg = true;
                }
                // Count the number of Python digits.
                var t = v;
                while (t) {
                    new_long.ob_digit[ndig] = t & PyLong_MASK;
                    t >>>= PyLong_SHIFT;
                    ++ndig;
                }
                new_long.ob_size = neg ? -ndig : ndig;
                return new_long;
            } else {
                var ndig, frac, expo, bits;
                var neg = false;

                if (isNaN(v)) {
                    @{{raise}}($new(@{{ValueError}}, B$str("cannot convert float NaN to integer")));
                }
                if (!isFinite(v)) {
                    @{{raise}}($new(@{{OverflowError}}, B$str("cannot convert float infinity to integer")));
                }
                if (v == 0) {
                    new_long.ob_digit[0] = 0;
                    new_long.ob_size = 0;
                    return new_long;
                }
                if (v < 0) {
                    v = -v;
                    neg = true;
                }
                // frac = frexp(dval, &expo); // dval = frac*2**expo; 0.0 <= frac < 1.0
                if (v == 0) {
                    frac = 0;
                    expo = 0;
                } else {
                    expo = Math.log(v)/$log2;
                    expo = (expo < 0 ? Math.ceil(expo):Math.floor(expo)) + 1;
                    frac = v / Math.pow(2.0, expo);
                }
                if (expo <= 0) {
                    return new_long;
                }
                ndig = Math.floor((expo-1) / PyLong_SHIFT) + 1;
                // ldexp(a,b) == a * (2**b)
                frac = frac * Math.pow(2.0, ((expo-1) % PyLong_SHIFT) + 1);
                for (var i = ndig; --i >= 0;) {
                    bits = Math.floor(frac);
                    new_long.ob_digit[i] = bits;
                    frac -= bits;
                    frac = frac * Math.pow(2.0, PyLong_SHIFT);
                }
                new_long.ob_size = neg ? -ndig : ndig;
                return new_long;
            }
            @{{raise}}($new(@{{ValueError}}, B$str("cannot convert " + @{{repr}}(@{{value}}) + "to integer")));
        } else if (typeof v == 'string') {
            var nchars;
            var text = v.replace(/^\s+/, "");
            var i = 0;
            var neg = false;

            switch (text.charAt(0)) {
                case '-':
                    neg = true;
                case '+':
                    text = text.substring(1).replace(/^\s+/, "");
            }

            if (!radix) {
                if (text == '0' || text.charAt(0) != '0') {
                    radix = 10;
                } else {
                    switch (text.charAt(1)) {
                        case 'x':
                        case 'X':
                            radix = 16;
                            break;
                        case 'o':
                        case 'O':
                            radix = 8;
                            break;
                        case 'b':
                        case 'B':
                            radix = 2;
                            break;
                        default:
                            radix = 8;
                            break;
                    }
                }
            } else if (radix < 1 || radix > 36) {
                @{{raise}}($new(@{{ValueError}}, B$str("long() arg 2 must be >= 2 and <= 36")));
            }
            if (text.charAt(0) == '0' && text.length > 1) {
                switch (text.charAt(1)) {
                    case 'x':
                    case 'X':
                        if (radix == 16) text = text.slice(2);
                        break;
                    case 'o':
                    case 'O':
                        if (radix == 8) text = text.slice(2);
                        break;
                    case 'b':
                    case 'B':
                        if (radix == 2) text = text.slice(2);
                        break;

                }
            }
            if ((radix & (radix - 1)) == 0) {
                // binary base: 2, 4, 8, ...
                var n, bits_per_char, accum, bits_in_accum, k, pdigit;
                var p = 0;

                n = radix;
                for (bits_per_char = -1; n; ++bits_per_char) {
                    n >>>= 1;
                }
                n = 0;
                while ($DigitValue[text.charCodeAt(p)] < radix) {
                    p++;
                }
                nchars = p;
                n = p * bits_per_char + PyLong_SHIFT-1; //14 = PyLong_SHIFT - 1
                if (n / bits_per_char < p) {
                    @{{raise}}($new(@{{ValueError}}, B$str("long string too large to convert")));
                }
                new_long.ob_size = n = Math.floor(n/PyLong_SHIFT);
                for (var i = 0; i < n; i++) {
                    new_long.ob_digit[i] = 0;
                }
                // Read string from right, and fill in long from left
                accum = 0;
                bits_in_accum = 0;
                pdigit = 0;
                while (--p >= 0) {
                    k = $DigitValue[text.charCodeAt(p)];
                    accum |= k << bits_in_accum;
                    bits_in_accum += bits_per_char;
                    if (bits_in_accum >= PyLong_SHIFT) {
                        new_long.ob_digit[pdigit] = accum & PyLong_MASK;
                        pdigit++;
                        accum >>>= PyLong_SHIFT;
                        bits_in_accum -= PyLong_SHIFT;
                    }
                }
                if (bits_in_accum) {
                    new_long.ob_digit[pdigit++] = accum;
                }
                while (pdigit < n) {
                    new_long.ob_digit[pdigit++] = 0;
                }
                long_normalize(new_long);
            } else {
                // Non-binary bases (such as radix == 10)
                var c, i, convwidth, convmultmax, convmult, pz, pzstop, scan, size_z;

                if ($log_base_PyLong_BASE[radix] == 0.0) {
                    var i = 1;
                    var convmax = radix;
                    $log_base_PyLong_BASE[radix] = Math.log(radix) / Math.log(PyLong_BASE);
                    while (1) {
                        var next = convmax * radix;
                        if (next > PyLong_BASE) break;
                        convmax = next;
                        ++i;
                    }
                    $convmultmax_base[radix] = convmax;
                    $convwidth_base[radix] = i;
                }
                scan = 0;
                while ($DigitValue[text.charCodeAt(scan)] < radix)
                    ++scan;
                nchars = scan;
                size_z = scan * $log_base_PyLong_BASE[radix] + 1;
                for (var i = 0; i < size_z; i ++) {
                    new_long.ob_digit[i] = 0;
                }
                new_long.ob_size = 0;
                convwidth = $convwidth_base[radix];
                convmultmax = $convmultmax_base[radix];
                for (var str = 0; str < scan;) {
                    c = $DigitValue[text.charCodeAt(str++)];
                    for (i = 1; i < convwidth && str != scan; ++i, ++str) {
                        c = c * radix + $DigitValue[text.charCodeAt(str)];
                    }
                    convmult = convmultmax;
                    if (i != convwidth) {
                        convmult = radix;
                        for ( ; i > 1; --i) convmult *= radix;
                    }
                    pz = 0;
                    pzstop = new_long.ob_size;
                    for (; pz < pzstop; ++pz) {
                        c += new_long.ob_digit[pz] * convmult;
                        new_long.ob_digit[pz] = c & PyLong_MASK;
                        c >>>= PyLong_SHIFT;
                    }
                    if (c) {
                        if (new_long.ob_size < size_z) {
                            new_long.ob_digit[pz] = c;
                            new_long.ob_size++;
                        } else {
                            new_long.ob_digit[new_long.ob_size] = c;
                        }
                    }
                }
            }
            text = text.slice(nchars);
            if (neg) new_long.ob_size = -new_long.ob_size;
            if (text.charAt(0) == 'l' || text.charAt(0) == 'L') text = text.slice(1);
            text = text.replace(/^\s+/, "");
            if (text.length === 0) {
                return new_long;
            }
            @{{raise}}($new(@{{ValueError}}, B$str("invalid literal for long() with base " + @{{!radix}} + ": " + @{{!value}})));
        } else {
            @{{raise}}($new(@{{TypeError}}, B$str("TypeError: long() argument must be a string or a number")));
        }
        if (isNaN(v) || !isFinite(v)) {
            @{{raise}}($new(@{{ValueError}}, B$str("invalid literal for long() with base " + @{{!radix}} + ": '" + @{{!v}} + "'")));
        }
        return new_long;
    });

    func(m$, null, f$, '__init__', 1, ['self', 'value', 'radix'], null, null, [N$], function(self, value, radix) {
        return N$;
    });

    func(m$, null, f$, '__str__', 1, ['self'], null, null, null, function($self) {
        return B$str(Format($self, 10, false, false));
    });

    func(m$, null, f$, '__repr__', 1, ['self'], null, null, null, function($self) {
        return B$str(Format($self, 10, true, false));
    });

    func(m$, null, f$, '__nonzero__', 1, ['self'], null, null, null, function($self) {
        return $self.ob_size != 0 ? @{{True}} : @{{False}};
    });

    func(m$, null, f$, '__cmp__', 1, ['self', 'b'], null, null, null, function($self, $b) {
        var sign;

        if ($self.ob_size != $b.ob_size) {
            if ($self.ob_size < $b.ob_size) return -1;
            return 1;
        }
        var i = $self.ob_size < 0 ? - $self.ob_size : $self.ob_size;
        while (--i >= 0 && $self.ob_digit[i] == $b.ob_digit[i])
            ;
        if (i < 0) return 0;
        if ($self.ob_digit[i] < $b.ob_digit[i]) {
            if ($self.ob_size < 0) return 1;
            return -1;
        }
        if ($self.ob_size < 0) return -1;
        return 1;
    });

    func(m$, null, f$, '__hash__', 1, ['self'], null, null, null, function($self) {
        var s = @{{long}}['$dict']['__str__']($self);
        var v = $self.valueOf();
        if (v.toString() == s) {
            return "#int#" + v;
        }
        return "#long#" + s;
    });

    func(m$, null, f$, '__invert__', 1, ['self'], null, null, null, function($self) {
        var x = @{{long}}['$dict']['__add__']($self, $const_long_1);
        x.ob_size = -x.ob_size;
        return x;
    });

    func(m$, null, f$, '__neg__', 1, ['self'], null, null, null, function($self) {
        var x = $new(@{{long}}, 0);
        x.ob_digit = $self.ob_digit.slice(0);
        x.ob_size = -$self.ob_size;
        return x;
    });

    func(m$, null, f$, '__abs__', 1, ['self'], null, null, null, function($self) {
        if ($self.ob_size >= 0) return $self;
        var x = $new(@{{long}}, 0);
        x.ob_digit = $self.ob_digit.slice(0);
        x.ob_size = -x.ob_size;
        return x;
    });

    func(m$, null, f$, '__lshift', 0, ['self', 'y'], null, null, null, function($self, $y) {
        var a, z, wordshift, remshift, oldsize, newsize,
            accum, i, j;
        if ($y < 0) {
            @{{raise}}($new(@{{ValueError}}, B$str("negative shift count")));
        }
        if ($y >= $max_float_int) {
            @{{raise}}($new(@{{ValueError}}, B$str("outrageous left shift count")));
        }
        a = $self;

        wordshift = Math.floor($y / PyLong_SHIFT);
        remshift  = $y - wordshift * PyLong_SHIFT;

        oldsize = a.ob_size < 0 ? -a.ob_size : a.ob_size;
        newsize = oldsize + wordshift;
        if (remshift) ++newsize;
        z = $new(@{{long}}, 0);
        z.ob_size = a.ob_size < 0 ? -newsize : newsize;
        for (i = 0; i < wordshift; i++) {
            z.ob_digit[i] = 0;
        }
        accum = 0;
        for (i = wordshift, j = 0; j < oldsize; i++, j++) {
            accum |= a.ob_digit[j] << remshift;
            z.ob_digit[i] = accum & PyLong_MASK;
            accum >>>= PyLong_SHIFT;
        }
        if (remshift) {
            z.ob_digit[newsize-1] = accum;
        }
        z = long_normalize(z);
        return z;
    });

    func(m$, null, f$, '__lshift__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__lshift']($y.__v);
            case 0x04:
                $y = $y.valueOf();
                return @{{long}}['$dict']['__lshift']($y);
            default: // test for javascript number
                if (typeof $y != "number") break;
                if ($y == Math.floor($y)) return @{{long}}['$dict']['__lshift']($self, $y);
                break;
        }
        return @{{NotImplemented}};
    });

    func(m$, null, f$, '__rlshift__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__lshift']($new(@{{long}}, $y.__v), $self.valueOf());
            case 0x04:
                return @{{long}}['$dict']['__lshift']($y, $self.valueOf());
        }
        return @{{NotImplemented}};
    });

    func(m$, null, f$, '__rshift', 0, ['self', 'y'], null, null, null, function($self, $y) {
        var a, z, size, wordshift, newsize, loshift, hishift,
            lomask, himask, i, j;
        if ($y.__number__ != 0x01) {
            $y = $y.valueOf();
        } else {
            if ($y != Math.floor($y)) {
                @{{raise}}($new(@{{TypeError}}, B$str("unsupported operand type(s) for >>: 'long' and 'float'")));
            }
        }
        if ($y < 0) {
            @{{raise}}($new(@{{ValueError}}, B$str("negative shift count")));
        }
        if ($y >= $max_float_int) {
            @{{raise}}($new(@{{ValueError}}, B$str("shift count too big")));
        }
        a = $self;
        size = $self.ob_size;
        if ($self.ob_size < 0) {
            size = -size;
            a = @{{long}}['$dict']['__add__']($self, $const_long_1);
            a.ob_size = -a.ob_size;
        }

        wordshift = Math.floor($y / PyLong_SHIFT);
        newsize = size - wordshift;
        if (newsize <= 0) {
            z = $const_long_0;
        } else {
            loshift = $y % PyLong_SHIFT;
            hishift = PyLong_SHIFT - loshift;
            lomask = (1 << hishift) - 1;
            himask = PyLong_MASK ^ lomask;
            z = $new(@{{long}}, 0);
            z.ob_size = a.ob_size < 0 ? -newsize : newsize;
            for (i = 0, j = wordshift; i < newsize; i++, j++) {
                z.ob_digit[i] = (a.ob_digit[j] >>> loshift) & lomask;
                if (i+1 < newsize) {
                    z.ob_digit[i] |=
                      (a.ob_digit[j+1] << hishift) & himask;
                }
            }
            z = long_normalize(z);
        }

        if ($self.ob_size < 0) {
            z = @{{long}}['$dict']['__add__'](z, $const_long_1);
            z.ob_size = -z.ob_size;
        }
        return z;
    });

    func(m$, null, f$, '__rshift__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__rshift']($y.__v);
            case 0x04:
                $y = $y.valueOf();
                return @{{long}}['$dict']['__rshift']($y);
            default: // test for javascript number
                if (typeof $y != "number") break;
                if ($y == Math.floor($y)) return @{{long}}['$dict']['__rshift']($self, $y);
                break;
        }
        return @{{NotImplemented}};
    });

    func(m$, null, f$, '__rrshift__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__rshift']($new(@{{long}}, $y.__v), $self.valueOf());
            case 0x04:
                return @{{long}}['$dict']['__rshift']($y, $self.valueOf());
        }
        return @{{NotImplemented}};
    });

    func(m$, null, f$, '__and', 0, ['self', 'b'], null, null, null, function($self, $b) {
        var a, maska, maskb, negz, size_a, size_b, size_z,
            i, z, diga, digb, v, op;

        a = $self;

        if (a.ob_size < 0) {
            a = @{{long}}['$dict']['__invert__'](a);
            maska = PyLong_MASK;
        } else {
            maska = 0;
        }
        if ($b.ob_size < 0) {
            $b = @{{long}}['$dict']['__invert__']($b);
            maskb = PyLong_MASK;
        } else {
            maskb = 0;
        }
        negz = 0;


            op = '&';
            if (maska && maskb) {
                op = '|';
                maska ^= PyLong_MASK;
                maskb ^= PyLong_MASK;
                negz = -1;
            }


        size_a = a.ob_size;
        size_b = $b.ob_size;
        size_z = op == '&'
                    ? (maska
                        ? size_b
                        : (maskb ? size_a : (size_a < size_b ? size_a : size_b)))
                    : (size_a > size_b ? size_a : size_b);
        z = $new(@{{long}}, 0);
        z.ob_size = size_z;

        switch (op) {
            case '&':
                for (i = 0; i < size_z; ++i) {
                    diga = (i < size_a ? a.ob_digit[i] : 0) ^ maska;
                    digb = (i < size_b ? $b.ob_digit[i] : 0) ^ maskb;
                    z.ob_digit[i] = diga & digb;
                }
                break;
            case '|':
                for (i = 0; i < size_z; ++i) {
                    diga = (i < size_a ? a.ob_digit[i] : 0) ^ maska;
                    digb = (i < size_b ? $b.ob_digit[i] : 0) ^ maskb;
                    z.ob_digit[i] = diga | digb;
                }
                break;
            case '^':
                for (i = 0; i < size_z; ++i) {
                    diga = (i < size_a ? a.ob_digit[i] : 0) ^ maska;
                    digb = (i < size_b ? $b.ob_digit[i] : 0) ^ maskb;
                    z.ob_digit[i] = diga ^ digb;
                }
                break;
        }
        z = long_normalize(z);
        if (negz == 0) {
            return z;
        }
        return @{{long}}['$dict']['__invert__'](z);
    });

    func(m$, null, f$, '__and__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__and']($new(@{{long}}, $y.__v));
            case 0x04:
                return @{{long}}['$dict']['__and']($self, $y);
            default: // test for javascript number
                if (typeof $y != "number") break;
                if ($y == Math.floor($y)) return @{{long}}['$dict']['__and']($self, $y);
                break;
        }
        return @{{NotImplemented}};
    });

    f$['__rand__'] = f$['__and__'];

    func(m$, null, f$, '__xor', 0, ['self', 'b'], null, null, null, function($self, $b) {
        var a,maska, maskb, negz, size_a, size_b, size_z,
            i, z, diga, digb, v, op;

        a = $self;

        if (a.ob_size < 0) {
            a = @{{long}}['$dict']['__invert__'](a);
            maska = PyLong_MASK;
        } else {
            maska = 0;
        }
        if ($b.ob_size < 0) {
            $b = @{{long}}['$dict']['__invert__']($b);
            maskb = PyLong_MASK;
        } else {
            maskb = 0;
        }
        negz = 0;


            op = '^';
            if (maska != maskb) {
                maska ^= PyLong_MASK;
                negz = -1;
            }


        size_a = a.ob_size;
        size_b = $b.ob_size;
        size_z = op == '&'
                    ? (maska
                        ? size_b
                        : (maskb ? size_a : (size_a < size_b ? size_a : size_b)))
                    : (size_a > size_b ? size_a : size_b);
        z = $new(@{{long}}, 0);
        z.ob_size = size_z;

        switch (op) {
            case '&':
                for (i = 0; i < size_z; ++i) {
                    diga = (i < size_a ? a.ob_digit[i] : 0) ^ maska;
                    digb = (i < size_b ? $b.ob_digit[i] : 0) ^ maskb;
                    z.ob_digit[i] = diga & digb;
                }
                break;
            case '|':
                for (i = 0; i < size_z; ++i) {
                    diga = (i < size_a ? a.ob_digit[i] : 0) ^ maska;
                    digb = (i < size_b ? $b.ob_digit[i] : 0) ^ maskb;
                    z.ob_digit[i] = diga | digb;
                }
                break;
            case '^':
                for (i = 0; i < size_z; ++i) {
                    diga = (i < size_a ? a.ob_digit[i] : 0) ^ maska;
                    digb = (i < size_b ? $b.ob_digit[i] : 0) ^ maskb;
                    z.ob_digit[i] = diga ^ digb;
                }
                break;
        }
        z = long_normalize(z);
        if (negz == 0) {
            return z;
        }
        return @{{long}}['$dict']['__invert__'](z);
    });

    func(m$, null, f$, '__xor__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__xor']($self, $new(@{{long}}, $y.__v));
            case 0x04:
                return @{{long}}['$dict']['__xor']($self, $y);
            default: // test for javascript number
                if (typeof $y != "number") break;
                if ($y == Math.floor($y)) return @{{long}}['$dict']['__xor']($self, $y);
                break;
        }
        return @{{NotImplemented}};
    });

    f$['__rxor__'] = f$['__xor__'];

    func(m$, null, f$, '__or', 0, ['self', 'b'], null, null, null, function($self, $b) {
        var a, maska, maskb, negz, size_a, size_b, size_z,
            i, z, diga, digb, v, op;

        a = $self;

        if (a.ob_size < 0) {
            a = @{{long}}['$dict']['__invert__'](a);
            maska = PyLong_MASK;
        } else {
            maska = 0;
        }
        if ($b.ob_size < 0) {
            $b = @{{long}}['$dict']['__invert__']($b);
            maskb = PyLong_MASK;
        } else {
            maskb = 0;
        }
        negz = 0;


            op = '|';
            if (maska || maskb) {
                op = '&';
                maska ^= PyLong_MASK;
                maskb ^= PyLong_MASK;
                negz = -1;
            }


        size_a = a.ob_size;
        size_b = $b.ob_size;
        size_z = op == '&'
                    ? (maska
                        ? size_b
                        : (maskb ? size_a : (size_a < size_b ? size_a : size_b)))
                    : (size_a > size_b ? size_a : size_b);
        z = $new(@{{long}}, 0);
        z.ob_size = size_z;

        switch (op) {
            case '&':
                for (i = 0; i < size_z; ++i) {
                    diga = (i < size_a ? a.ob_digit[i] : 0) ^ maska;
                    digb = (i < size_b ? $b.ob_digit[i] : 0) ^ maskb;
                    z.ob_digit[i] = diga & digb;
                }
                break;
            case '|':
                for (i = 0; i < size_z; ++i) {
                    diga = (i < size_a ? a.ob_digit[i] : 0) ^ maska;
                    digb = (i < size_b ? $b.ob_digit[i] : 0) ^ maskb;
                    z.ob_digit[i] = diga | digb;
                }
                break;
            case '^':
                for (i = 0; i < size_z; ++i) {
                    diga = (i < size_a ? a.ob_digit[i] : 0) ^ maska;
                    digb = (i < size_b ? $b.ob_digit[i] : 0) ^ maskb;
                    z.ob_digit[i] = diga ^ digb;
                }
                break;
        }
        z = long_normalize(z);
        if (negz == 0) {
            return z;
        }
        return @{{long}}['$dict']['__invert__'](z);
    });

    func(m$, null, f$, '__or__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__or']($self, $new(@{{long}}, $y.__v));
            case 0x04:
                return @{{long}}['$dict']['__or']($self, $y);
            default: // test for javascript number
                if (typeof $y != "number") break;
                if ($y == Math.floor($y)) return @{{long}}['$dict']['__or']($self, $y);
                break;
        }
        return @{{NotImplemented}};
    });

    f$['__ror__'] = f$['__or__'];

    func(m$, null, f$, '__oct__', 1, ['self'], null, null, null, function($self) {
        return B$str(Format($self, 8, true, false));
    });

    func(m$, null, f$, '__hex__', 1, ['self'], null, null, null, function($self) {
        return B$str(Format($self, 16, true, false));
    });

    func(m$, null, f$, '__add', 0, ['self', 'b'], null, null, null, function($self, $b) {
        var a = $self, z;
        if (a.ob_size < 0) {
            if ($b.ob_size < 0) {
                z = x_add(a, $b);
                z.ob_size = -(z.ob_size);
            }
            else {
                z = x_sub($b, a);
            }
        }
        else {
            z = $b.ob_size < 0 ? x_sub(a, $b) : x_add(a, $b);
        }
        return z;
    });

    func(m$, null, f$, '__add__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__add']($self, $new(@{{long}}, $y.__v));
            case 0x04:
                return @{{long}}['$dict']['__add']($self, $y);
        }
        return @{{NotImplemented}};
    });

    f$['__radd__'] = f$['__add__'];

    func(m$, null, f$, '__sub', 0, ['self', 'b'], null, null, null, function($self, $b) {
        var a = $self, z;
        if (a.ob_size < 0) {
            z = $b.ob_size < 0 ? x_sub(a, $b) : x_add(a, $b);
            z.ob_size = -(z.ob_size);
        }
        else {
            z = $b.ob_size < 0 ?  x_add(a, $b) : x_sub(a, $b);
        }
        return z;
    });

    func(m$, null, f$, '__sub__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__sub']($self, $new(@{{long}}, $y.__v));
            case 0x04:
                return @{{long}}['$dict']['__sub']($self, $y);
        }
        return @{{NotImplemented}};
    });

    func(m$, null, f$, '__rsub__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__sub']($new(@{{long}}, $y.__v), $self);
            case 0x04:
                return @{{long}}['$dict']['__sub']($y, $self);
        }
        return @{{NotImplemented}};
    });

    func(m$, null, f$, '__mul', 0, ['self', 'b'], null, null, null, function($self, $b) {
        //var z = k_mul($self, $b);
        var z = x_mul($self, $b);
        if (($self.ob_size ^ $b.ob_size) < 0)
            z.ob_size = -(z.ob_size);
        return z;
    });

    func(m$, null, f$, '__mul__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__mul']($self, $new(@{{long}}, $y.__v));
            case 0x04:
                return @{{long}}['$dict']['__mul']($self, $y);
        }
        return @{{NotImplemented}};
    });

    f$['__rmul__'] = f$['__mul__'];

    func(m$, null, f$, '__div', 0, ['self', 'b'], null, null, null, function($self, $b) {
        var div = $new(@{{long}}, 0);
        l_divmod($self, $b, div, null);
        return div;
    });

    func(m$, null, f$, '__div__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__div']($self, $new(@{{long}}, $y.__v));
            case 0x04:
                return @{{long}}['$dict']['__div']($self, $y);
        }
        return @{{NotImplemented}};
    });

    func(m$, null, f$, '__rdiv__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__div']($new(@{{long}}, y.__v), $self);
            case 0x04:
                return @{{long}}['$dict']['__div']($y, $self);
        }
        return @{{NotImplemented}};
    });

    func(m$, null, f$, '__mod', 0, ['self', 'b'], null, null, null, function($self, $b) {
        var mod = $new(@{{long}}, 0);
        l_divmod($self, $b, null, mod);
        return mod;
    });

    func(m$, null, f$, '__mod__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__mod']($self, $new(@{{long}}, $y.__v));
            case 0x04:
                return @{{long}}['$dict']['__mod']($self, $y);
        }
        return @{{NotImplemented}};
    });

    func(m$, null, f$, '__rmod__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__mod']($new(@{{long}}, $y.__v), $self);
            case 0x04:
                return @{{long}}['$dict']['__mod']($y, $self);
        }
        return @{{NotImplemented}};
    });

    func(m$, null, f$, '__divmod', 0, ['self', 'b'], null, null, null, function($self, $b) {
        var div = $new(@{{long}}, 0);
        var mod = $new(@{{long}}, 0);
        l_divmod($self, $b, div, mod);
        return @{{tuple}}([div, mod]);
    });

    func(m$, null, f$, '__divmod__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__divmod']($self, $new(@{{long}}, $y.__v));
            case 0x04:
                return @{{long}}['$dict']['__divmod']($self, $y);
        }
        return @{{NotImplemented}};
    });

    func(m$, null, f$, '__rdivmod__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__divmod']($new(@{{long}}, y.__v), $self);
            case 0x04:
                return @{{long}}['$dict']['__divmod']($y, $self);
        }
        return @{{NotImplemented}};
    });

    func(m$, null, f$, '__floordiv', 0, ['self', 'b'], null, null, null, function($self, $b) {
        var div = $new(@{{long}}, 0);
        l_divmod($self, $b, div, null);
        return div;
    });

    func(m$, null, f$, '__floordiv__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__floordiv']($self, $new(@{{long}}, $y.__v));
            case 0x04:
                return @{{long}}['$dict']['__floordiv']($self, $y);
        }
        return @{{NotImplemented}};
    });

    func(m$, null, f$, '__rfloordiv__', 1, ['self', 'y'], null, null, null, function($self, $y) {
        switch ($y.__number__) {
            case 0x02:
                return @{{long}}['$dict']['__floordiv']($new(@{{long}}, y.__v), $self);
            case 0x04:
                return @{{long}}['$dict']['__floordiv']($y, $self);
        }
        return @{{NotImplemented}};
    });

    func(m$, null, f$, '__pow', 0, ['self', 'w', 'x'], null, null, null, function($self, $w, $x) {
        var v = $self;
        var a, b, c, negativeOutput = 0, z, i, j, k, temp, bi;
        var table = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];

        a = $self;
        b = $w.__number__ == 0x04 ? $w : $new(@{{long}}, $w);
        if ($x === null || typeof $x == "undefined") {
            c = null;
        } else {
            c = $x.__number__ == 0x04 ? $x : $new(@{{long}}, $x);
        }

        if (b.ob_size < 0) {
            if (c !== null) {
                @{{raise}}($new(@{{TypeError}}, B$str("pow() 2nd argument cannot be negative when 3rd argument specified")));
            }
            return Math.pow(v.valueOf(), $w.valueOf());
        }

        if (c !== null) {
            if (c.ob_size == 0) {
                @{{raise}}($new(@{{ValueError}}, B$str("pow() 3rd argument cannot be 0")));
            }
            if (c.ob_size < 0) {
                negativeOutput = 1;
                temp = $pow_temp_c;
                temp.ob_digit = c.ob_digit.slice(0);
                temp.ob_size = -c.ob_size;
                c = temp;
            }
            if (c.ob_size == 1 && c.ob_digit[0] == 1) {
                return $const_long_0;
            }
            if (a.ob_size < 0) {
                temp = $pow_temp_a;
                l_divmod(a, c, null, temp);
                a = temp;
            }
        }
        z = $new(@{{long}}, 1);
        temp = $pow_temp_z;
        if (b.ob_size <= FIVEARY_CUTOFF) {
            for (i = b.ob_size - 1; i >= 0; --i) {
                bi = b.ob_digit[i];
                for (j = 1 << (PyLong_SHIFT-1); j != 0; j >>>= 1) {
                    z = @{{long}}['$dict']['__mul'](z, z);
                    if (c !== null) {
                        l_divmod(z, c, null, temp);
                        z.ob_digit = temp.ob_digit.slice(0);
                        z.ob_size = temp.ob_size;
                    }
                    if (bi & j) {
                        z = @{{long}}['$dict']['__mul'](z, a);
                        if (c !== null) {
                            l_divmod(z, c, null, temp);
                            z.ob_digit = temp.ob_digit.slice(0);
                            z.ob_size = temp.ob_size;
                        }
                    }
                }
            }
        } else {
            table[0] = z;
            for (i = 1; i < 32; ++i) {
                table[i] = @{{long}}['$dict']['__mul'](table[i-1], a);
                if (c !== null) {
                    l_divmod(table[i], c, null, temp);
                    table[i].ob_digit = temp.ob_digit.slice(0);
                    table[i].ob_size = temp.ob_size;
                }
            }
            for (i = b.ob_size - 1; i >= 0; --i) {
                bi = b.ob_digit[i];
                for (j = PyLong_SHIFT - 5; j >= 0; j -= 5) {
                    var index = (bi >>> j) & 0x1f;
                    for (k = 0; k < 5; ++k) {
                        z = @{{long}}['$dict']['__mul'](z, z);
                        if (c !== null) {
                            l_divmod(z, c, null, temp);
                            z.ob_digit = temp.ob_digit.slice(0);
                            z.ob_size = temp.ob_size;
                        }
                    }
                    if (index) {
                        z = @{{long}}['$dict']['__mul'](z, table[index]);
                        if (c !== null) {
                            l_divmod(z, c, null, temp);
                            z.ob_digit = temp.ob_digit.slice(0);
                            z.ob_size = temp.ob_size;
                        }
                    }
                }
            }
        }

        if ((c !== null) && negativeOutput &&
            (z.ob_size != 0) && (c.ob_size != 0)) {
            z = @{{long}}['$dict']['__sub__'](z, c);
        }
        return z;
    });

    func(m$, null, f$, '__pow__', 1, ['self', 'y', 'z'], null, null, null, function($self, $y, $z) {
        switch ($y.__number__) {
            case 0x02:
                if (typeof $z == "undefined")
                    return @{{long}}['$dict']['__pow']($self, $new(@{{long}}, $y.__v), null);
                switch ($z.__number) {
                    case 0x02:
                        return @{{long}}['$dict']['__pow']($self, $new(@{{long}}, $y.__v), $new(@{{long}}, $z));
                    case 0x04:
                        return @{{long}}['$dict']['__pow']($self, $new(@{{long}}, $y.__v), $z);
                }
                break;
            case 0x04:
                if (typeof $z == "undefined")
                    return @{{long}}['$dict']['__pow']($self, $y, null);
                switch (z.__number) {
                    case 0x02:
                        return @{{long}}['$dict']['__pow']($self, $y, $new(@{{long}}, $z));
                    case 0x04:
                        return @{{long}}['$dict']['__pow']($self, $y, $z);
                }
                break;
        }
        return @{{NotImplemented}};
    });


    var $const_long_0 = $new(@{{long}}, 0),
        $const_long_1 = $new(@{{long}}, 1);
    // Since javascript is single threaded:
    var $l_divmod_div = $new(@{{long}}, 0),
        $l_divmod_mod = $new(@{{long}}, 0),
        $x_divrem_v = $new(@{{long}}, 0),
        $x_divrem_w = $new(@{{long}}, 0),
        $pow_temp_a = $new(@{{long}}, 0),
        $pow_temp_c = $new(@{{long}}, 0),
        $pow_temp_z = $new(@{{long}}, 0);
})();""")


# Now we're done with the str/int/bool/long/NonType classes and
# can initialize the constants
JS("""
init_short_names$(true);
init_constants$(true);
@{{__name__}} = B$str('__builtin__');
@{{__builtins__}} = m$;


func(m$, null, f$, 'op_not', 1, ['object'], null, null, null, function($object) {

    var v = $object.valueOf();
    switch (v) {
        case null:
        case false:
        case 0:
        case '':
            return @{{True}};
        case true:
        case 1:
            return @{{False}};
    }
    if (typeof v == 'number' || typeof v == 'string') {
        return @{{False}};
    }
    if ($object['$inst'] === true) {
        var mro$, attr, attrs = ['__nonzero__', '__len__'];
        for (var i = 0; i < attrs.length; i++) {
            attr = attrs[i];
            v = [][1];
            var mro$ = $object['__mro__'];
            var _meth_src = $object;
            switch ($object['$inst']) {
                case true:
                    if ($object['__class__'] === @{{module}}) {
                        v = $object['$dict'][attr];
                        break;
                    } else if ($object['__class__'] === @{{function}}) {
                        switch (attr.charAt(0)) {
                            case 'i':
                            case '_':
                                v = $object[attr];
                        }
                        break;
                    }
                    var _noraise$ = @{{noraise}};
                    var ga;
                    mro$ = $object['__class__']['__mro__'];
                    for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                        var _mro$ = mro$[mro_i$];
                        var ga = _mro$['__getattribute__'];
                        if (typeof ga == "undefined") {
                            if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                                continue;
                            }
                            ga = _mro$['$dict']['__getattribute__'];
                        }
                        if ($object['__class__']['$inst'] === false && $object['__class__'] !== @{{module}} && typeof $object != "undefined" && typeof $object['$inst'] != "undefined") {
                            switch (ga['__class__']) {
                                case @{{function}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $object['$inst'] === true ? $object['__class__'] : $object;
                                    _new_dst$['im_func'] = ga;
                                    _new_dst$['im_self'] = $object['$inst'] === true ? $object : null;
                                    ga = _new_dst$;
                                    break;
                                case @{{staticmethod}}:
                                    ga = ga['im_func'];
                                    break;
                                case @{{classmethod}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $object['$inst'] === true ? $object['__class__'] : $object;
                                    _new_dst$['im_func'] = ga['im_func'];
                                    _new_dst$['im_self'] = $object['$inst'] === true ? $object['__class__'] : $object;
                                    ga = _new_dst$;
                                    break;
                                case @{{bool}}: // Some known to be non-descriptors
                                case @{{int}}:
                                case @{{long}}:
                                case @{{str}}:
                                    break;
                                default:
                                    // check for __get__ method in ga
                                    if (ga['$inst'] === true) {
                                        var get$ = @{{_getattr}}(ga, '__get__');
                                        if (typeof get$ != 'undefined') {
                                            ga = @{{fcall}}(this, null, get$, ga, $object, $object['__class__']);
                                        }
                                    }
                                    break;
                            }
                        }
                        @{{noraise}} = @{{AttributeError}};
                        v = @{{fcall}}(this, null, ga, _mro$, attr);
                        @{{noraise}} = _noraise$;
                        if (v === @{{AttributeError}}) {
                            v = [][1];
                        }
                        _meth_src = $object['__class__'];
                        $object = $object['__class__'];
                        break;
                    }
                    if (typeof v == "undefined") {
                        if (typeof $object['$dict'] != "undefined") {
                            v = $object['$dict'][attr];
                            if (typeof v != "undefined") {
                                if (v !== {}[attr]) {
                                    break;
                                }
                                v = [][1];
                            }
                        }
                        switch (attr.charAt(0)) {
                            case 'i':
                            case '_':
                                v = $object[attr];
                        }
                        if (typeof v != "undefined") {
                            break;
                        }
                    }
                case false:
                    if (typeof v == "undefined") {
                        var _mro$, ga;
                        if ($object['$inst'] === true) {
                            _meth_src = $object['__class__'];
                        } else {
                            switch (attr.charAt(0)) {
                                case 'i':
                                case '_':
                                    v = $object[attr];
                            }
                            if (typeof v != "undefined") {
                                break;
                            }

                        }
                        if (typeof v == "undefined") {
                            for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                                _mro$ = mro$[mro_i$];
                                v = _mro$['$dict'][attr];
                                if (typeof v != "undefined") {
                                    if (v !== {}[attr]) {
                                        break;
                                    }
                                    v = [][1];
                                }
                                switch (attr.charAt(0)) {
                                    case 'i':
                                    case '_':
                                        v = _mro$[attr];
                                }
                                if (typeof v != "undefined") {
                                    break;
                                }
                            }
                        }
                        if (typeof v == "undefined" && attr !== '__get__') {
                            for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                                _mro$ = mro$[mro_i$];
                                if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                    continue;
                                }
                                ga = _mro$['$dict']['__getattr__'];
                                if ($object['__class__']['$inst'] === false && $object['__class__'] !== @{{module}} && typeof $object != "undefined" && typeof $object['$inst'] != "undefined") {
                                    switch (ga['__class__']) {
                                        case @{{function}}:
                                            var _new_dst$ = function ( ) {
                                                var args = Array.prototype.slice.call(arguments);
                                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                    if (arguments.callee['im_self'] !== null) {
                                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                    }
                                                }
                                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                                if (typeof a == "undefined") {
                                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                }
                                                if (args.length >= 3) {
                                                    var len = args.length;
                                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                    }
                                                }
                                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                            _new_dst$['toString'] = function ( ) {
                                                try {
                                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                } catch (e) {
                                                }
                                                try {
                                                    return "<" + this.__class__.__name__ + " instance>";
                                                } catch (e) {
                                                }
                                                return "<instance>";
                                            };
                                            _new_dst$['$inst'] = true;
                                            if (typeof @{{instancemethod}} == "undefined") {
                                                debugger;
                                            }
                                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                _new_dst$['__dict__'] = B$dict();
                                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                            }
                                            _new_dst$['__class__'] = @{{instancemethod}};
                                            _new_dst$['im_class'] = $object['$inst'] === true ? $object['__class__'] : $object;
                                            _new_dst$['im_func'] = ga;
                                            _new_dst$['im_self'] = $object['$inst'] === true ? $object : null;
                                            ga = _new_dst$;
                                            break;
                                        case @{{staticmethod}}:
                                            ga = ga['im_func'];
                                            break;
                                        case @{{classmethod}}:
                                            var _new_dst$ = function ( ) {
                                                var args = Array.prototype.slice.call(arguments);
                                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                    if (arguments.callee['im_self'] !== null) {
                                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                    }
                                                }
                                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                                if (typeof a == "undefined") {
                                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                }
                                                if (args.length >= 3) {
                                                    var len = args.length;
                                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                    }
                                                }
                                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                            _new_dst$['toString'] = function ( ) {
                                                try {
                                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                } catch (e) {
                                                }
                                                try {
                                                    return "<" + this.__class__.__name__ + " instance>";
                                                } catch (e) {
                                                }
                                                return "<instance>";
                                            };
                                            _new_dst$['$inst'] = true;
                                            if (typeof @{{instancemethod}} == "undefined") {
                                                debugger;
                                            }
                                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                _new_dst$['__dict__'] = B$dict();
                                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                            }
                                            _new_dst$['__class__'] = @{{instancemethod}};
                                            _new_dst$['im_class'] = $object['$inst'] === true ? $object['__class__'] : $object;
                                            _new_dst$['im_func'] = ga['im_func'];
                                            _new_dst$['im_self'] = $object['$inst'] === true ? $object['__class__'] : $object;
                                            ga = _new_dst$;
                                            break;
                                        case @{{bool}}: // Some known to be non-descriptors
                                        case @{{int}}:
                                        case @{{long}}:
                                        case @{{str}}:
                                            break;
                                        default:
                                            // check for __get__ method in ga
                                            if (ga['$inst'] === true) {
                                                var get$ = @{{_getattr}}(ga, '__get__');
                                                if (typeof get$ != 'undefined') {
                                                    ga = @{{fcall}}(this, null, get$, ga, $object, $object['__class__']);
                                                }
                                            }
                                            break;
                                    }
                                }
                                @{{noraise}} = @{{AttributeError}};
                                v = @{{fcall}}(this, null, ga, _mro$, attr);
                                @{{noraise}} = _noraise$;
                                if (v === @{{AttributeError}}) {
                                    v = [][1];
                                }
                                // TODO : unbind v ?
                                break;
                            }
                        }
                    }
                    break;
                default:
                    v = $object[attr];
                    if (typeof v == "undefined" && typeof $object['$dict'] != "undefined") {
                        v = $object['$dict'][attr];
                    }
            }
            if (typeof v != "undefined") {
                if (_meth_src['$inst'] === false && $object['__class__'] !== @{{module}} && typeof v != "undefined" && typeof v['$inst'] != "undefined") {
                    switch (v['__class__']) {
                        case @{{function}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $object['$inst'] === true ? $object['__class__'] : $object;
                            _new_dst$['im_func'] = v;
                            _new_dst$['im_self'] = $object['$inst'] === true ? $object : null;
                            v = _new_dst$;
                            break;
                        case @{{staticmethod}}:
                            v = v['im_func'];
                            break;
                        case @{{classmethod}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $object['$inst'] === true ? $object['__class__'] : $object;
                            _new_dst$['im_func'] = v['im_func'];
                            _new_dst$['im_self'] = $object['$inst'] === true ? $object['__class__'] : $object;
                            v = _new_dst$;
                            break;
                        case @{{bool}}: // Some known to be non-descriptors
                        case @{{int}}:
                        case @{{long}}:
                        case @{{str}}:
                            break;
                        default:
                            // check for __get__ method in v
                            if (v['$inst'] === true) {
                                var get$ = @{{_getattr}}(v, '__get__');
                                if (typeof get$ != 'undefined') {
                                    v = @{{fcall}}(this, null, get$, v, $object, $object['__class__']);
                                }
                            }
                            break;
                    }
                }
                v = @{{fcall}}(this, null, v, $object);
                switch (attr) {
                    case '__nonzero__':
                        return v.__v ? @{{False}} : @{{True}};
                    case '__len__':
                        return v.__v != 0 ? @{{False}} : @{{True}};
                }
            }
        }
    }
    return @{{False}};
});
func(m$, null, f$, 'test_not', 1, ['object'], null, null, null, function($object) {

    var v = $object.valueOf();
    switch (v) {
        case null:
        case false:
        case 0:
        case '':
            return true;
        case true:
        case 1:
            return false;
    }
    if (typeof v == 'number' || typeof v == 'string') {
        return false;
    }
    if ($object['$inst'] === true) {
        var mro$, attr, attrs = ['__nonzero__', '__len__'];
        for (var i = 0; i < attrs.length; i++) {
            attr = attrs[i];
            v = [][1];
            var mro$ = $object['__mro__'];
            var _meth_src = $object;
            switch ($object['$inst']) {
                case true:
                    if ($object['__class__'] === @{{module}}) {
                        v = $object['$dict'][attr];
                        break;
                    } else if ($object['__class__'] === @{{function}}) {
                        switch (attr.charAt(0)) {
                            case 'i':
                            case '_':
                                v = $object[attr];
                        }
                        break;
                    }
                    var _noraise$ = @{{noraise}};
                    var ga;
                    mro$ = $object['__class__']['__mro__'];
                    for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                        var _mro$ = mro$[mro_i$];
                        var ga = _mro$['__getattribute__'];
                        if (typeof ga == "undefined") {
                            if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                                continue;
                            }
                            ga = _mro$['$dict']['__getattribute__'];
                        }
                        if ($object['__class__']['$inst'] === false && $object['__class__'] !== @{{module}} && typeof $object != "undefined" && typeof $object['$inst'] != "undefined") {
                            switch (ga['__class__']) {
                                case @{{function}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $object['$inst'] === true ? $object['__class__'] : $object;
                                    _new_dst$['im_func'] = ga;
                                    _new_dst$['im_self'] = $object['$inst'] === true ? $object : null;
                                    ga = _new_dst$;
                                    break;
                                case @{{staticmethod}}:
                                    ga = ga['im_func'];
                                    break;
                                case @{{classmethod}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $object['$inst'] === true ? $object['__class__'] : $object;
                                    _new_dst$['im_func'] = ga['im_func'];
                                    _new_dst$['im_self'] = $object['$inst'] === true ? $object['__class__'] : $object;
                                    ga = _new_dst$;
                                    break;
                                case @{{bool}}: // Some known to be non-descriptors
                                case @{{int}}:
                                case @{{long}}:
                                case @{{str}}:
                                    break;
                                default:
                                    // check for __get__ method in ga
                                    if (ga['$inst'] === true) {
                                        var get$ = @{{_getattr}}(ga, '__get__');
                                        if (typeof get$ != 'undefined') {
                                            ga = @{{fcall}}(this, null, get$, ga, $object, $object['__class__']);
                                        }
                                    }
                                    break;
                            }
                        }
                        @{{noraise}} = @{{AttributeError}};
                        v = @{{fcall}}(this, null, ga, _mro$, attr);
                        @{{noraise}} = _noraise$;
                        if (v === @{{AttributeError}}) {
                            v = [][1];
                        }
                        _meth_src = $object['__class__'];
                        $object = $object['__class__'];
                        break;
                    }
                    if (typeof v == "undefined") {
                        if (typeof $object['$dict'] != "undefined") {
                            v = $object['$dict'][attr];
                            if (typeof v != "undefined") {
                                if (v !== {}[attr]) {
                                    break;
                                }
                                v = [][1];
                            }
                        }
                        switch (attr.charAt(0)) {
                            case 'i':
                            case '_':
                                v = $object[attr];
                        }
                        if (typeof v != "undefined") {
                            break;
                        }
                    }
                case false:
                    if (typeof v == "undefined") {
                        var _mro$, ga;
                        if ($object['$inst'] === true) {
                            _meth_src = $object['__class__'];
                        } else {
                            switch (attr.charAt(0)) {
                                case 'i':
                                case '_':
                                    v = $object[attr];
                            }
                            if (typeof v != "undefined") {
                                break;
                            }

                        }
                        if (typeof v == "undefined") {
                            for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                                _mro$ = mro$[mro_i$];
                                v = _mro$['$dict'][attr];
                                if (typeof v != "undefined") {
                                    if (v !== {}[attr]) {
                                        break;
                                    }
                                    v = [][1];
                                }
                                switch (attr.charAt(0)) {
                                    case 'i':
                                    case '_':
                                        v = _mro$[attr];
                                }
                                if (typeof v != "undefined") {
                                    break;
                                }
                            }
                        }
                        if (typeof v == "undefined" && attr !== '__get__') {
                            for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                                _mro$ = mro$[mro_i$];
                                if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                    continue;
                                }
                                ga = _mro$['$dict']['__getattr__'];
                                if ($object['__class__']['$inst'] === false && $object['__class__'] !== @{{module}} && typeof $object != "undefined" && typeof $object['$inst'] != "undefined") {
                                    switch (ga['__class__']) {
                                        case @{{function}}:
                                            var _new_dst$ = function ( ) {
                                                var args = Array.prototype.slice.call(arguments);
                                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                    if (arguments.callee['im_self'] !== null) {
                                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                    }
                                                }
                                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                                if (typeof a == "undefined") {
                                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                }
                                                if (args.length >= 3) {
                                                    var len = args.length;
                                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                    }
                                                }
                                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                            _new_dst$['toString'] = function ( ) {
                                                try {
                                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                } catch (e) {
                                                }
                                                try {
                                                    return "<" + this.__class__.__name__ + " instance>";
                                                } catch (e) {
                                                }
                                                return "<instance>";
                                            };
                                            _new_dst$['$inst'] = true;
                                            if (typeof @{{instancemethod}} == "undefined") {
                                                debugger;
                                            }
                                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                _new_dst$['__dict__'] = B$dict();
                                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                            }
                                            _new_dst$['__class__'] = @{{instancemethod}};
                                            _new_dst$['im_class'] = $object['$inst'] === true ? $object['__class__'] : $object;
                                            _new_dst$['im_func'] = ga;
                                            _new_dst$['im_self'] = $object['$inst'] === true ? $object : null;
                                            ga = _new_dst$;
                                            break;
                                        case @{{staticmethod}}:
                                            ga = ga['im_func'];
                                            break;
                                        case @{{classmethod}}:
                                            var _new_dst$ = function ( ) {
                                                var args = Array.prototype.slice.call(arguments);
                                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                    if (arguments.callee['im_self'] !== null) {
                                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                    }
                                                }
                                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                                if (typeof a == "undefined") {
                                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                                }
                                                if (args.length >= 3) {
                                                    var len = args.length;
                                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                    }
                                                }
                                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                            _new_dst$['toString'] = function ( ) {
                                                try {
                                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                                } catch (e) {
                                                }
                                                try {
                                                    return "<" + this.__class__.__name__ + " instance>";
                                                } catch (e) {
                                                }
                                                return "<instance>";
                                            };
                                            _new_dst$['$inst'] = true;
                                            if (typeof @{{instancemethod}} == "undefined") {
                                                debugger;
                                            }
                                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                                _new_dst$['__dict__'] = B$dict();
                                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                            }
                                            _new_dst$['__class__'] = @{{instancemethod}};
                                            _new_dst$['im_class'] = $object['$inst'] === true ? $object['__class__'] : $object;
                                            _new_dst$['im_func'] = ga['im_func'];
                                            _new_dst$['im_self'] = $object['$inst'] === true ? $object['__class__'] : $object;
                                            ga = _new_dst$;
                                            break;
                                        case @{{bool}}: // Some known to be non-descriptors
                                        case @{{int}}:
                                        case @{{long}}:
                                        case @{{str}}:
                                            break;
                                        default:
                                            // check for __get__ method in ga
                                            if (ga['$inst'] === true) {
                                                var get$ = @{{_getattr}}(ga, '__get__');
                                                if (typeof get$ != 'undefined') {
                                                    ga = @{{fcall}}(this, null, get$, ga, $object, $object['__class__']);
                                                }
                                            }
                                            break;
                                    }
                                }
                                @{{noraise}} = @{{AttributeError}};
                                v = @{{fcall}}(this, null, ga, _mro$, attr);
                                @{{noraise}} = _noraise$;
                                if (v === @{{AttributeError}}) {
                                    v = [][1];
                                }
                                // TODO : unbind v ?
                                break;
                            }
                        }
                    }
                    break;
                default:
                    v = $object[attr];
                    if (typeof v == "undefined" && typeof $object['$dict'] != "undefined") {
                        v = $object['$dict'][attr];
                    }
            }
            if (typeof v != "undefined") {
                if (_meth_src['$inst'] === false && $object['__class__'] !== @{{module}} && typeof v != "undefined" && typeof v['$inst'] != "undefined") {
                    switch (v['__class__']) {
                        case @{{function}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $object['$inst'] === true ? $object['__class__'] : $object;
                            _new_dst$['im_func'] = v;
                            _new_dst$['im_self'] = $object['$inst'] === true ? $object : null;
                            v = _new_dst$;
                            break;
                        case @{{staticmethod}}:
                            v = v['im_func'];
                            break;
                        case @{{classmethod}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $object['$inst'] === true ? $object['__class__'] : $object;
                            _new_dst$['im_func'] = v['im_func'];
                            _new_dst$['im_self'] = $object['$inst'] === true ? $object['__class__'] : $object;
                            v = _new_dst$;
                            break;
                        case @{{bool}}: // Some known to be non-descriptors
                        case @{{int}}:
                        case @{{long}}:
                        case @{{str}}:
                            break;
                        default:
                            // check for __get__ method in v
                            if (v['$inst'] === true) {
                                var get$ = @{{_getattr}}(v, '__get__');
                                if (typeof get$ != 'undefined') {
                                    v = @{{fcall}}(this, null, get$, v, $object, $object['__class__']);
                                }
                            }
                            break;
                    }
                }
                v = @{{fcall}}(this, null, v, $object);
                switch (attr) {
                    case '__nonzero__':
                        return v.__v ? false : true;
                    case '__len__':
                        return v.__v != 0 ? false : true;
                }
            }
        }
    }
    return false;
});

func(m$, null, f$, 'op_neg', 1, ['v'], null, null, null, function($v) {
    if (typeof $v != "undefined" && $v !== null) {
        var f, mro$;
        f = [][1];
        var mro$ = $v['__mro__'];
        var _meth_src = $v;
        switch ($v['$inst']) {
            case true:
                if ($v['__class__'] === @{{module}}) {
                    f = $v['$dict']['__neg__'];
                    break;
                } else if ($v['__class__'] === @{{function}}) {
                    switch ('__neg__'.charAt(0)) {
                        case 'i':
                        case '_':
                            f = $v['__neg__'];
                    }
                    break;
                }
                var _noraise$ = @{{noraise}};
                var ga;
                mro$ = $v['__class__']['__mro__'];
                for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                    var _mro$ = mro$[mro_i$];
                    var ga = _mro$['__getattribute__'];
                    if (typeof ga == "undefined") {
                        if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattribute__'];
                    }
                    if ($v['__class__']['$inst'] === false && $v['__class__'] !== @{{module}} && typeof $v != "undefined" && typeof $v['$inst'] != "undefined") {
                        switch (ga['__class__']) {
                            case @{{function}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                _new_dst$['im_func'] = ga;
                                _new_dst$['im_self'] = $v['$inst'] === true ? $v : null;
                                ga = _new_dst$;
                                break;
                            case @{{staticmethod}}:
                                ga = ga['im_func'];
                                break;
                            case @{{classmethod}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                _new_dst$['im_func'] = ga['im_func'];
                                _new_dst$['im_self'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                ga = _new_dst$;
                                break;
                            case @{{bool}}: // Some known to be non-descriptors
                            case @{{int}}:
                            case @{{long}}:
                            case @{{str}}:
                                break;
                            default:
                                // check for __get__ method in ga
                                if (ga['$inst'] === true) {
                                    var get$ = @{{_getattr}}(ga, '__get__');
                                    if (typeof get$ != 'undefined') {
                                        ga = @{{fcall}}(this, null, get$, ga, $v, $v['__class__']);
                                    }
                                }
                                break;
                        }
                    }
                    @{{noraise}} = @{{AttributeError}};
                    f = @{{fcall}}(this, null, ga, _mro$, '__neg__');
                    @{{noraise}} = _noraise$;
                    if (f === @{{AttributeError}}) {
                        f = [][1];
                    }
                    _meth_src = $v['__class__'];
                    $v = $v['__class__'];
                    break;
                }
                if (typeof f == "undefined") {
                    if (typeof $v['$dict'] != "undefined") {
                        f = $v['$dict']['__neg__'];
                        if (typeof f != "undefined") {
                            if (f !== {}['__neg__']) {
                                break;
                            }
                            f = [][1];
                        }
                    }
                    switch ('__neg__'.charAt(0)) {
                        case 'i':
                        case '_':
                            f = $v['__neg__'];
                    }
                    if (typeof f != "undefined") {
                        break;
                    }
                }
            case false:
                if (typeof f == "undefined") {
                    var _mro$, ga;
                    if ($v['$inst'] === true) {
                        _meth_src = $v['__class__'];
                    } else {
                        switch ('__neg__'.charAt(0)) {
                            case 'i':
                            case '_':
                                f = $v['__neg__'];
                        }
                        if (typeof f != "undefined") {
                            break;
                        }

                    }
                    if (typeof f == "undefined") {
                        for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            f = _mro$['$dict']['__neg__'];
                            if (typeof f != "undefined") {
                                if (f !== {}['__neg__']) {
                                    break;
                                }
                                f = [][1];
                            }
                            switch ('__neg__'.charAt(0)) {
                                case 'i':
                                case '_':
                                    f = _mro$['__neg__'];
                            }
                            if (typeof f != "undefined") {
                                break;
                            }
                        }
                    }
                    if (typeof f == "undefined" && '__neg__' !== '__get__') {
                        for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                continue;
                            }
                            ga = _mro$['$dict']['__getattr__'];
                            if ($v['__class__']['$inst'] === false && $v['__class__'] !== @{{module}} && typeof $v != "undefined" && typeof $v['$inst'] != "undefined") {
                                switch (ga['__class__']) {
                                    case @{{function}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                        _new_dst$['im_func'] = ga;
                                        _new_dst$['im_self'] = $v['$inst'] === true ? $v : null;
                                        ga = _new_dst$;
                                        break;
                                    case @{{staticmethod}}:
                                        ga = ga['im_func'];
                                        break;
                                    case @{{classmethod}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                        _new_dst$['im_func'] = ga['im_func'];
                                        _new_dst$['im_self'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                        ga = _new_dst$;
                                        break;
                                    case @{{bool}}: // Some known to be non-descriptors
                                    case @{{int}}:
                                    case @{{long}}:
                                    case @{{str}}:
                                        break;
                                    default:
                                        // check for __get__ method in ga
                                        if (ga['$inst'] === true) {
                                            var get$ = @{{_getattr}}(ga, '__get__');
                                            if (typeof get$ != 'undefined') {
                                                ga = @{{fcall}}(this, null, get$, ga, $v, $v['__class__']);
                                            }
                                        }
                                        break;
                                }
                            }
                            @{{noraise}} = @{{AttributeError}};
                            f = @{{fcall}}(this, null, ga, _mro$, '__neg__');
                            @{{noraise}} = _noraise$;
                            if (f === @{{AttributeError}}) {
                                f = [][1];
                            }
                            // TODO : unbind f ?
                            break;
                        }
                    }
                }
                break;
            default:
                f = $v['__neg__'];
                if (typeof f == "undefined" && typeof $v['$dict'] != "undefined") {
                    f = $v['$dict']['__neg__'];
                }
        }
        if (typeof f == 'function') return f($v);
    }
    return @{{raise}}($new(@{{TypeError}}, B$str(@{{sprintf}}("bad operand type for unary -: '%r'", [$v]))));
});

func(m$, null, f$, 'op_inv', 1, ['v'], null, null, null, function($v) {
    if (typeof $v != "undefined" && $v !== null) {
        var f, mro$;
        f = [][1];
        var mro$ = $v['__mro__'];
        var _meth_src = $v;
        switch ($v['$inst']) {
            case true:
                if ($v['__class__'] === @{{module}}) {
                    f = $v['$dict']['__invert__'];
                    break;
                } else if ($v['__class__'] === @{{function}}) {
                    switch ('__invert__'.charAt(0)) {
                        case 'i':
                        case '_':
                            f = $v['__invert__'];
                    }
                    break;
                }
                var _noraise$ = @{{noraise}};
                var ga;
                mro$ = $v['__class__']['__mro__'];
                for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                    var _mro$ = mro$[mro_i$];
                    var ga = _mro$['__getattribute__'];
                    if (typeof ga == "undefined") {
                        if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattribute__'];
                    }
                    if ($v['__class__']['$inst'] === false && $v['__class__'] !== @{{module}} && typeof $v != "undefined" && typeof $v['$inst'] != "undefined") {
                        switch (ga['__class__']) {
                            case @{{function}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                _new_dst$['im_func'] = ga;
                                _new_dst$['im_self'] = $v['$inst'] === true ? $v : null;
                                ga = _new_dst$;
                                break;
                            case @{{staticmethod}}:
                                ga = ga['im_func'];
                                break;
                            case @{{classmethod}}:
                                var _new_dst$ = function ( ) {
                                    var args = Array.prototype.slice.call(arguments);
                                    if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                        if (arguments.callee['im_self'] !== null) {
                                            return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                        }
                                    }
                                    var a = @{{_getattr}}(arguments.callee, '__call__');
                                    if (typeof a == "undefined") {
                                        @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                    }
                                    if (args.length >= 3) {
                                        var len = args.length;
                                        if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                            (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                            (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                            return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                    }
                                    return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                                _new_dst$['toString'] = function ( ) {
                                    try {
                                        return @{{mcall}}(this, null, this, '__str__').valueOf();
                                    } catch (e) {
                                    }
                                    try {
                                        return "<" + this.__class__.__name__ + " instance>";
                                    } catch (e) {
                                    }
                                    return "<instance>";
                                };
                                _new_dst$['$inst'] = true;
                                if (typeof @{{instancemethod}} == "undefined") {
                                    debugger;
                                }
                                if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                    _new_dst$['__dict__'] = B$dict();
                                    _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                }
                                _new_dst$['__class__'] = @{{instancemethod}};
                                _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                _new_dst$['im_func'] = ga['im_func'];
                                _new_dst$['im_self'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                ga = _new_dst$;
                                break;
                            case @{{bool}}: // Some known to be non-descriptors
                            case @{{int}}:
                            case @{{long}}:
                            case @{{str}}:
                                break;
                            default:
                                // check for __get__ method in ga
                                if (ga['$inst'] === true) {
                                    var get$ = @{{_getattr}}(ga, '__get__');
                                    if (typeof get$ != 'undefined') {
                                        ga = @{{fcall}}(this, null, get$, ga, $v, $v['__class__']);
                                    }
                                }
                                break;
                        }
                    }
                    @{{noraise}} = @{{AttributeError}};
                    f = @{{fcall}}(this, null, ga, _mro$, '__invert__');
                    @{{noraise}} = _noraise$;
                    if (f === @{{AttributeError}}) {
                        f = [][1];
                    }
                    _meth_src = $v['__class__'];
                    $v = $v['__class__'];
                    break;
                }
                if (typeof f == "undefined") {
                    if (typeof $v['$dict'] != "undefined") {
                        f = $v['$dict']['__invert__'];
                        if (typeof f != "undefined") {
                            if (f !== {}['__invert__']) {
                                break;
                            }
                            f = [][1];
                        }
                    }
                    switch ('__invert__'.charAt(0)) {
                        case 'i':
                        case '_':
                            f = $v['__invert__'];
                    }
                    if (typeof f != "undefined") {
                        break;
                    }
                }
            case false:
                if (typeof f == "undefined") {
                    var _mro$, ga;
                    if ($v['$inst'] === true) {
                        _meth_src = $v['__class__'];
                    } else {
                        switch ('__invert__'.charAt(0)) {
                            case 'i':
                            case '_':
                                f = $v['__invert__'];
                        }
                        if (typeof f != "undefined") {
                            break;
                        }

                    }
                    if (typeof f == "undefined") {
                        for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            f = _mro$['$dict']['__invert__'];
                            if (typeof f != "undefined") {
                                if (f !== {}['__invert__']) {
                                    break;
                                }
                                f = [][1];
                            }
                            switch ('__invert__'.charAt(0)) {
                                case 'i':
                                case '_':
                                    f = _mro$['__invert__'];
                            }
                            if (typeof f != "undefined") {
                                break;
                            }
                        }
                    }
                    if (typeof f == "undefined" && '__invert__' !== '__get__') {
                        for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                            _mro$ = mro$[mro_i$];
                            if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                                continue;
                            }
                            ga = _mro$['$dict']['__getattr__'];
                            if ($v['__class__']['$inst'] === false && $v['__class__'] !== @{{module}} && typeof $v != "undefined" && typeof $v['$inst'] != "undefined") {
                                switch (ga['__class__']) {
                                    case @{{function}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                        _new_dst$['im_func'] = ga;
                                        _new_dst$['im_self'] = $v['$inst'] === true ? $v : null;
                                        ga = _new_dst$;
                                        break;
                                    case @{{staticmethod}}:
                                        ga = ga['im_func'];
                                        break;
                                    case @{{classmethod}}:
                                        var _new_dst$ = function ( ) {
                                            var args = Array.prototype.slice.call(arguments);
                                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                                if (arguments.callee['im_self'] !== null) {
                                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                                }
                                            }
                                            var a = @{{_getattr}}(arguments.callee, '__call__');
                                            if (typeof a == "undefined") {
                                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                            }
                                            if (args.length >= 3) {
                                                var len = args.length;
                                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                                }
                                            }
                                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                        }
                                        _new_dst$['toString'] = function ( ) {
                                            try {
                                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                                            } catch (e) {
                                            }
                                            try {
                                                return "<" + this.__class__.__name__ + " instance>";
                                            } catch (e) {
                                            }
                                            return "<instance>";
                                        };
                                        _new_dst$['$inst'] = true;
                                        if (typeof @{{instancemethod}} == "undefined") {
                                            debugger;
                                        }
                                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                            _new_dst$['__dict__'] = B$dict();
                                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                        }
                                        _new_dst$['__class__'] = @{{instancemethod}};
                                        _new_dst$['im_class'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                        _new_dst$['im_func'] = ga['im_func'];
                                        _new_dst$['im_self'] = $v['$inst'] === true ? $v['__class__'] : $v;
                                        ga = _new_dst$;
                                        break;
                                    case @{{bool}}: // Some known to be non-descriptors
                                    case @{{int}}:
                                    case @{{long}}:
                                    case @{{str}}:
                                        break;
                                    default:
                                        // check for __get__ method in ga
                                        if (ga['$inst'] === true) {
                                            var get$ = @{{_getattr}}(ga, '__get__');
                                            if (typeof get$ != 'undefined') {
                                                ga = @{{fcall}}(this, null, get$, ga, $v, $v['__class__']);
                                            }
                                        }
                                        break;
                                }
                            }
                            @{{noraise}} = @{{AttributeError}};
                            f = @{{fcall}}(this, null, ga, _mro$, '__invert__');
                            @{{noraise}} = _noraise$;
                            if (f === @{{AttributeError}}) {
                                f = [][1];
                            }
                            // TODO : unbind f ?
                            break;
                        }
                    }
                }
                break;
            default:
                f = $v['__invert__'];
                if (typeof f == "undefined" && typeof $v['$dict'] != "undefined") {
                    f = $v['$dict']['__invert__'];
                }
        }
        if (typeof f == 'function') return f($v);
    }
    return @{{raise}}($new(@{{TypeError}}, B$str(@{{sprintf}}("bad operand type for unary ~: '%r'", [$v]))));
});


func(m$, null, f$, 'op_is', 1, ['a', 'b'], null, null, null, function($a, $b) {
    if ($a === $b) {
        return @{{True}};
    }
    if ($a !== null && $b !== null) {
        switch (($a.__number__ << 8) | $b.__number__) {
            case 0x0101:
                return $a == $b ? @{{True}} : @{{False}};
            case 0x0202:
                return $a.__v == $b.__v ? @{{True}} : @{{False}};
            case 0x0404:
                return @{{long}}['$dict'].__cmp__($a, $b) == 0 ? @{{True}} : @{{False}};
        }
    }
    return @{{False}}
});
func(m$, null, f$, 'op_is_not', 1, ['a', 'b'], null, null, null, function($a, $b) {
    if ($a === $b) {
        return @{{False}};
    }
    if ($a !== null && $b !== null) {
        switch (($a.__number__ << 8) | $b.__number__) {
            case 0x0101:
                return $a == $b ? @{{False}} : @{{True}};
            case 0x0202:
                return $a.__v == $b.__v ? @{{False}} : @{{True}};
            case 0x0404:
                return @{{long}}['$dict'].__cmp__($a, $b) == 0 ? @{{False}} : @{{True}};
        }
    }
    return @{{True}}
});
func(m$, null, f$, 'op_eq', 1, ['a', 'b'], null, null, null, function($a, $b) {
    if ($a !== null && $b !== null) {
        switch (($a.__number__ << 8) | $b.__number__) {
            case 0x0101:
            case 0x0401:
                return $a.valueOf() == $b.valueOf() ? @{{True}} : @{{False}};
            case 0x0102:
                return $a.valueOf() == $b.__v ? @{{True}} : @{{False}};
            case 0x0201:
                return $a.__v == $b.valueOf() ? @{{True}} : @{{False}};
            case 0x0202:
                return $a.__v == $b.__v ? @{{True}} : @{{False}};
            case 0x0104:
            case 0x0204:
                $a = $new(@{{long}}, $a.valueOf());
            case 0x0404:
                if ($a['__class__'] !== @{{long}}) break;
                return @{{long}}['$dict']['__cmp__']($a, $b).valueOf() == 0 ? @{{True}} : @{{False}};
            case 0x0402:
                if ($a['__class__'] !== @{{long}}) break;
                return @{{long}}['$dict']['__cmp__']($a, $new(@{{long}}, $b.valueOf())).valueOf() == 0 ? @{{True}} : @{{False}};
        }
        var v = @{{fcall}}(this, null, @{{cmp}}, null, $a, $b).valueOf();
        return v === null ? @{{False}} : (v == 0 ? @{{True}} : @{{False}});
    }
    return @{{False}};
});
func(m$, null, f$, 'op_ne', 1, ['a', 'b'], null, null, null, function($a, $b) {
    if ($a !== null && $b !== null) {
        switch (($a.__number__ << 8) | $b.__number__) {
            case 0x0101:
            case 0x0401:
                return $a.valueOf() != $b.valueOf() ? @{{True}} : @{{False}};
            case 0x0102:
                return $a.valueOf() != $b.__v ? @{{True}} : @{{False}};
            case 0x0201:
                return $a.__v != $b.valueOf() ? @{{True}} : @{{False}};
            case 0x0202:
                return $a.__v != $b.__v ? @{{True}} : @{{False}};
            case 0x0104:
            case 0x0204:
                $a = $new(@{{long}}, $a.valueOf());
            case 0x0404:
                if ($a['__class__'] !== @{{long}}) break;
                return @{{long}}['$dict']['__cmp__']($a, $b).valueOf() != 0 ? @{{True}} : @{{False}};
            case 0x0402:
                if ($a['__class__'] !== @{{long}}) break;
                return @{{long}}['$dict']['__cmp__']($a, $new(@{{long}}, $b.valueOf())).valueOf() != 0 ? @{{True}} : @{{False}};
        }
        var v = @{{fcall}}(this, null, @{{cmp}}, null, $a, $b).valueOf();
        return v === null ? @{{True}} : (v != 0 ? @{{True}} : @{{False}});
    }
    return @{{False}};
});
func(m$, null, f$, 'op_le', 1, ['a', 'b'], null, null, null, function($a, $b) {
    if ($a !== null && $b !== null) {
        switch (($a.__number__ << 8) | $b.__number__) {
            case 0x0101:
            case 0x0401:
                return $a.valueOf() <= $b.valueOf() ? @{{True}} : @{{False}};
            case 0x0102:
                return $a.valueOf() <= $b.__v ? @{{True}} : @{{False}};
            case 0x0201:
                return $a.__v <= $b.valueOf() ? @{{True}} : @{{False}};
            case 0x0202:
                return $a.__v <= $b.__v ? @{{True}} : @{{False}};
            case 0x0104:
            case 0x0204:
                $a = $new(@{{long}}, $a.valueOf());
            case 0x0404:
                if ($a['__class__'] !== @{{long}}) break;
                return @{{long}}['$dict']['__cmp__']($a, $b).valueOf() <= 0 ? @{{True}} : @{{False}};
            case 0x0402:
                if ($a['__class__'] !== @{{long}}) break;
                return @{{long}}['$dict']['__cmp__']($a, $new(@{{long}}, $b.valueOf())).valueOf() <= 0 ? @{{True}} : @{{False}};
        }
        var v = @{{fcall}}(this, null, @{{cmp}}, null, $a, $b).valueOf();
        return v === null ? @{{False}} : (v <= 0 ? @{{True}} : @{{False}});
    }
    return @{{False}};
});
func(m$, null, f$, 'op_lt', 1, ['a', 'b'], null, null, null, function($a, $b) {
    if ($a !== null && $b !== null) {
        switch (($a.__number__ << 8) | $b.__number__) {
            case 0x0101:
            case 0x0401:
                return $a.valueOf() < $b.valueOf() ? @{{True}} : @{{False}};
            case 0x0102:
                return $a.valueOf() < $b.__v ? @{{True}} : @{{False}};
            case 0x0201:
                return $a.__v < $b.valueOf() ? @{{True}} : @{{False}};
            case 0x0202:
                return $a.__v < $b.__v ? @{{True}} : @{{False}};
            case 0x0104:
            case 0x0204:
                $a = $new(@{{long}}, $a.valueOf());
            case 0x0404:
                if ($a['__class__'] !== @{{long}}) break;
                return @{{long}}['$dict']['__cmp__']($a, $b).valueOf() < 0 ? @{{True}} : @{{False}};
            case 0x0402:
                if ($a['__class__'] !== @{{long}}) break;
                return @{{long}}['$dict']['__cmp__']($a, $new(@{{long}}, $b.valueOf())).valueOf() < 0 ? @{{True}} : @{{False}};
        }
        var v = @{{fcall}}(this, null, @{{cmp}}, null, $a, $b).valueOf();
        return v === null ? @{{False}} : (v < 0 ? @{{True}} : @{{False}});
    }
    return @{{False}};
});
func(m$, null, f$, 'op_ge', 1, ['a', 'b'], null, null, null, function($a, $b) {
    if ($a !== null && $b !== null) {
        switch (($a.__number__ << 8) | $b.__number__) {
            case 0x0101:
            case 0x0401:
                return $a.valueOf() >= $b.valueOf() ? @{{True}} : @{{False}};
            case 0x0102:
                return $a.valueOf() >= $b.__v ? @{{True}} : @{{False}};
            case 0x0201:
                return $a.__v >= $b.valueOf() ? @{{True}} : @{{False}};
            case 0x0202:
                return $a.__v >= $b.__v ? @{{True}} : @{{False}};
            case 0x0104:
            case 0x0204:
                $a = $new(@{{long}}, $a.valueOf());
            case 0x0404:
                if ($a['__class__'] !== @{{long}}) break;
                return @{{long}}['$dict']['__cmp__']($a, $b).valueOf() >= 0 ? @{{True}} : @{{False}};
            case 0x0402:
                if ($a['__class__'] !== @{{long}}) break;
                return @{{long}}['$dict']['__cmp__']($a, $new(@{{long}}, $b.valueOf())).valueOf() >= 0 ? @{{True}} : @{{False}};
        }
        var v = @{{fcall}}(this, null, @{{cmp}}, null, $a, $b).valueOf();
        return v === null ? @{{False}} : (v >= 0 ? @{{True}} : @{{False}});
    }
    return @{{False}};
});
func(m$, null, f$, 'op_gt', 1, ['a', 'b'], null, null, null, function($a, $b) {
    if ($a !== null && $b !== null) {
        switch (($a.__number__ << 8) | $b.__number__) {
            case 0x0101:
            case 0x0401:
                return $a.valueOf() > $b.valueOf() ? @{{True}} : @{{False}};
            case 0x0102:
                return $a.valueOf() > $b.__v ? @{{True}} : @{{False}};
            case 0x0201:
                return $a.__v > $b.valueOf() ? @{{True}} : @{{False}};
            case 0x0202:
                return $a.__v > $b.__v ? @{{True}} : @{{False}};
            case 0x0104:
            case 0x0204:
                $a = $new(@{{long}}, $a.valueOf());
            case 0x0404:
                if ($a['__class__'] !== @{{long}}) break;
                return @{{long}}['$dict']['__cmp__']($a, $b).valueOf() > 0 ? @{{True}} : @{{False}};
            case 0x0402:
                if ($a['__class__'] !== @{{long}}) break;
                return @{{long}}['$dict']['__cmp__']($a, $new(@{{long}}, $b.valueOf())).valueOf() > 0 ? @{{True}} : @{{False}};
        }
        var v = @{{fcall}}(this, null, @{{cmp}}, null, $a, $b).valueOf();
        return v === null ? @{{False}} : (v > 0 ? @{{True}} : @{{False}});
    }
    return @{{False}};
});
func(m$, null, f$, 'op_in', 1, ['a', 'b'], null, null, null, function($a, $b) {
    var i, mro$;
    i = [][1];
    var mro$ = $b['__mro__'];
    var _meth_src = $b;
    switch ($b['$inst']) {
        case true:
            if ($b['__class__'] === @{{module}}) {
                i = $b['$dict']['__contains__'];
                break;
            } else if ($b['__class__'] === @{{function}}) {
                switch ('__contains__'.charAt(0)) {
                    case 'i':
                    case '_':
                        i = $b['__contains__'];
                }
                break;
            }
            var _noraise$ = @{{noraise}};
            var ga;
            mro$ = $b['__class__']['__mro__'];
            for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                var _mro$ = mro$[mro_i$];
                var ga = _mro$['__getattribute__'];
                if (typeof ga == "undefined") {
                    if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                        continue;
                    }
                    ga = _mro$['$dict']['__getattribute__'];
                }
                if ($b['__class__']['$inst'] === false && $b['__class__'] !== @{{module}} && typeof $b != "undefined" && typeof $b['$inst'] != "undefined") {
                    switch (ga['__class__']) {
                        case @{{function}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $b['$inst'] === true ? $b['__class__'] : $b;
                            _new_dst$['im_func'] = ga;
                            _new_dst$['im_self'] = $b['$inst'] === true ? $b : null;
                            ga = _new_dst$;
                            break;
                        case @{{staticmethod}}:
                            ga = ga['im_func'];
                            break;
                        case @{{classmethod}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $b['$inst'] === true ? $b['__class__'] : $b;
                            _new_dst$['im_func'] = ga['im_func'];
                            _new_dst$['im_self'] = $b['$inst'] === true ? $b['__class__'] : $b;
                            ga = _new_dst$;
                            break;
                        case @{{bool}}: // Some known to be non-descriptors
                        case @{{int}}:
                        case @{{long}}:
                        case @{{str}}:
                            break;
                        default:
                            // check for __get__ method in ga
                            if (ga['$inst'] === true) {
                                var get$ = @{{_getattr}}(ga, '__get__');
                                if (typeof get$ != 'undefined') {
                                    ga = @{{fcall}}(this, null, get$, ga, $b, $b['__class__']);
                                }
                            }
                            break;
                    }
                }
                @{{noraise}} = @{{AttributeError}};
                i = @{{fcall}}(this, null, ga, _mro$, '__contains__');
                @{{noraise}} = _noraise$;
                if (i === @{{AttributeError}}) {
                    i = [][1];
                }
                _meth_src = $b['__class__'];
                $b = $b['__class__'];
                break;
            }
            if (typeof i == "undefined") {
                if (typeof $b['$dict'] != "undefined") {
                    i = $b['$dict']['__contains__'];
                    if (typeof i != "undefined") {
                        if (i !== {}['__contains__']) {
                            break;
                        }
                        i = [][1];
                    }
                }
                switch ('__contains__'.charAt(0)) {
                    case 'i':
                    case '_':
                        i = $b['__contains__'];
                }
                if (typeof i != "undefined") {
                    break;
                }
            }
        case false:
            if (typeof i == "undefined") {
                var _mro$, ga;
                if ($b['$inst'] === true) {
                    _meth_src = $b['__class__'];
                } else {
                    switch ('__contains__'.charAt(0)) {
                        case 'i':
                        case '_':
                            i = $b['__contains__'];
                    }
                    if (typeof i != "undefined") {
                        break;
                    }

                }
                if (typeof i == "undefined") {
                    for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        i = _mro$['$dict']['__contains__'];
                        if (typeof i != "undefined") {
                            if (i !== {}['__contains__']) {
                                break;
                            }
                            i = [][1];
                        }
                        switch ('__contains__'.charAt(0)) {
                            case 'i':
                            case '_':
                                i = _mro$['__contains__'];
                        }
                        if (typeof i != "undefined") {
                            break;
                        }
                    }
                }
                if (typeof i == "undefined" && '__contains__' !== '__get__') {
                    for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattr__'];
                        if ($b['__class__']['$inst'] === false && $b['__class__'] !== @{{module}} && typeof $b != "undefined" && typeof $b['$inst'] != "undefined") {
                            switch (ga['__class__']) {
                                case @{{function}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $b['$inst'] === true ? $b['__class__'] : $b;
                                    _new_dst$['im_func'] = ga;
                                    _new_dst$['im_self'] = $b['$inst'] === true ? $b : null;
                                    ga = _new_dst$;
                                    break;
                                case @{{staticmethod}}:
                                    ga = ga['im_func'];
                                    break;
                                case @{{classmethod}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $b['$inst'] === true ? $b['__class__'] : $b;
                                    _new_dst$['im_func'] = ga['im_func'];
                                    _new_dst$['im_self'] = $b['$inst'] === true ? $b['__class__'] : $b;
                                    ga = _new_dst$;
                                    break;
                                case @{{bool}}: // Some known to be non-descriptors
                                case @{{int}}:
                                case @{{long}}:
                                case @{{str}}:
                                    break;
                                default:
                                    // check for __get__ method in ga
                                    if (ga['$inst'] === true) {
                                        var get$ = @{{_getattr}}(ga, '__get__');
                                        if (typeof get$ != 'undefined') {
                                            ga = @{{fcall}}(this, null, get$, ga, $b, $b['__class__']);
                                        }
                                    }
                                    break;
                            }
                        }
                        @{{noraise}} = @{{AttributeError}};
                        i = @{{fcall}}(this, null, ga, _mro$, '__contains__');
                        @{{noraise}} = _noraise$;
                        if (i === @{{AttributeError}}) {
                            i = [][1];
                        }
                        // TODO : unbind i ?
                        break;
                    }
                }
            }
            break;
        default:
            i = $b['__contains__'];
            if (typeof i == "undefined" && typeof $b['$dict'] != "undefined") {
                i = $b['$dict']['__contains__'];
            }
    }
    if (typeof i != "undefined") {
        if (_meth_src['$inst'] === false && $b['__class__'] !== @{{module}} && typeof i != "undefined" && typeof i['$inst'] != "undefined") {
            switch (i['__class__']) {
                case @{{function}}:
                    var _new_dst$ = function ( ) {
                        var args = Array.prototype.slice.call(arguments);
                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                            if (arguments.callee['im_self'] !== null) {
                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                            }
                        }
                        var a = @{{_getattr}}(arguments.callee, '__call__');
                        if (typeof a == "undefined") {
                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                        }
                        if (args.length >= 3) {
                            var len = args.length;
                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                        }
                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                    }
                    _new_dst$['toString'] = function ( ) {
                        try {
                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                        } catch (e) {
                        }
                        try {
                            return "<" + this.__class__.__name__ + " instance>";
                        } catch (e) {
                        }
                        return "<instance>";
                    };
                    _new_dst$['$inst'] = true;
                    if (typeof @{{instancemethod}} == "undefined") {
                        debugger;
                    }
                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                        _new_dst$['__dict__'] = B$dict();
                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                    }
                    _new_dst$['__class__'] = @{{instancemethod}};
                    _new_dst$['im_class'] = $b['$inst'] === true ? $b['__class__'] : $b;
                    _new_dst$['im_func'] = i;
                    _new_dst$['im_self'] = $b['$inst'] === true ? $b : null;
                    i = _new_dst$;
                    break;
                case @{{staticmethod}}:
                    i = i['im_func'];
                    break;
                case @{{classmethod}}:
                    var _new_dst$ = function ( ) {
                        var args = Array.prototype.slice.call(arguments);
                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                            if (arguments.callee['im_self'] !== null) {
                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                            }
                        }
                        var a = @{{_getattr}}(arguments.callee, '__call__');
                        if (typeof a == "undefined") {
                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                        }
                        if (args.length >= 3) {
                            var len = args.length;
                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                        }
                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                    }
                    _new_dst$['toString'] = function ( ) {
                        try {
                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                        } catch (e) {
                        }
                        try {
                            return "<" + this.__class__.__name__ + " instance>";
                        } catch (e) {
                        }
                        return "<instance>";
                    };
                    _new_dst$['$inst'] = true;
                    if (typeof @{{instancemethod}} == "undefined") {
                        debugger;
                    }
                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                        _new_dst$['__dict__'] = B$dict();
                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                    }
                    _new_dst$['__class__'] = @{{instancemethod}};
                    _new_dst$['im_class'] = $b['$inst'] === true ? $b['__class__'] : $b;
                    _new_dst$['im_func'] = i['im_func'];
                    _new_dst$['im_self'] = $b['$inst'] === true ? $b['__class__'] : $b;
                    i = _new_dst$;
                    break;
                case @{{bool}}: // Some known to be non-descriptors
                case @{{int}}:
                case @{{long}}:
                case @{{str}}:
                    break;
                default:
                    // check for __get__ method in i
                    if (i['$inst'] === true) {
                        var get$ = @{{_getattr}}(i, '__get__');
                        if (typeof get$ != 'undefined') {
                            i = @{{fcall}}(this, null, get$, i, $b, $b['__class__']);
                        }
                    }
                    break;
            }
        }
        return @{{fcall}}(this, null, i,  $b, $a).valueOf() ? @{{True}} : @{{False}};
    }
    var __iter__ = @{{iter}}($b);
    var $stopiter = @{{stopiter}}
    for (;;) {
        @{{stopiter}} = true;
        i = @{{mcall}}(this, null, __iter__, 'next');
        @{{stopiter}} = $stopiter;
        if (i === @{{StopIter}}) {
            return @{{False}};
        }
        if (@{{op_eq}}(i, $a)) {
            return @{{True}};
        }
    }

});
func(m$, null, f$, 'op_not_in', 1, ['a', 'b'], null, null, null, function($a, $b) {
    var i, mro$;
    i = [][1];
    var mro$ = $b['__mro__'];
    var _meth_src = $b;
    switch ($b['$inst']) {
        case true:
            if ($b['__class__'] === @{{module}}) {
                i = $b['$dict']['__contains__'];
                break;
            } else if ($b['__class__'] === @{{function}}) {
                switch ('__contains__'.charAt(0)) {
                    case 'i':
                    case '_':
                        i = $b['__contains__'];
                }
                break;
            }
            var _noraise$ = @{{noraise}};
            var ga;
            mro$ = $b['__class__']['__mro__'];
            for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                var _mro$ = mro$[mro_i$];
                var ga = _mro$['__getattribute__'];
                if (typeof ga == "undefined") {
                    if (typeof _mro$ == "undefined" || typeof _mro$['$dict']['__getattribute__'] == "undefined") {
                        continue;
                    }
                    ga = _mro$['$dict']['__getattribute__'];
                }
                if ($b['__class__']['$inst'] === false && $b['__class__'] !== @{{module}} && typeof $b != "undefined" && typeof $b['$inst'] != "undefined") {
                    switch (ga['__class__']) {
                        case @{{function}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $b['$inst'] === true ? $b['__class__'] : $b;
                            _new_dst$['im_func'] = ga;
                            _new_dst$['im_self'] = $b['$inst'] === true ? $b : null;
                            ga = _new_dst$;
                            break;
                        case @{{staticmethod}}:
                            ga = ga['im_func'];
                            break;
                        case @{{classmethod}}:
                            var _new_dst$ = function ( ) {
                                var args = Array.prototype.slice.call(arguments);
                                if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                    if (arguments.callee['im_self'] !== null) {
                                        return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                    }
                                }
                                var a = @{{_getattr}}(arguments.callee, '__call__');
                                if (typeof a == "undefined") {
                                    @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                }
                                if (args.length >= 3) {
                                    var len = args.length;
                                    if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                        (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                        (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                        return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                }
                                return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                            _new_dst$['toString'] = function ( ) {
                                try {
                                    return @{{mcall}}(this, null, this, '__str__').valueOf();
                                } catch (e) {
                                }
                                try {
                                    return "<" + this.__class__.__name__ + " instance>";
                                } catch (e) {
                                }
                                return "<instance>";
                            };
                            _new_dst$['$inst'] = true;
                            if (typeof @{{instancemethod}} == "undefined") {
                                debugger;
                            }
                            if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                _new_dst$['__dict__'] = B$dict();
                                _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                            }
                            _new_dst$['__class__'] = @{{instancemethod}};
                            _new_dst$['im_class'] = $b['$inst'] === true ? $b['__class__'] : $b;
                            _new_dst$['im_func'] = ga['im_func'];
                            _new_dst$['im_self'] = $b['$inst'] === true ? $b['__class__'] : $b;
                            ga = _new_dst$;
                            break;
                        case @{{bool}}: // Some known to be non-descriptors
                        case @{{int}}:
                        case @{{long}}:
                        case @{{str}}:
                            break;
                        default:
                            // check for __get__ method in ga
                            if (ga['$inst'] === true) {
                                var get$ = @{{_getattr}}(ga, '__get__');
                                if (typeof get$ != 'undefined') {
                                    ga = @{{fcall}}(this, null, get$, ga, $b, $b['__class__']);
                                }
                            }
                            break;
                    }
                }
                @{{noraise}} = @{{AttributeError}};
                i = @{{fcall}}(this, null, ga, _mro$, '__contains__');
                @{{noraise}} = _noraise$;
                if (i === @{{AttributeError}}) {
                    i = [][1];
                }
                _meth_src = $b['__class__'];
                $b = $b['__class__'];
                break;
            }
            if (typeof i == "undefined") {
                if (typeof $b['$dict'] != "undefined") {
                    i = $b['$dict']['__contains__'];
                    if (typeof i != "undefined") {
                        if (i !== {}['__contains__']) {
                            break;
                        }
                        i = [][1];
                    }
                }
                switch ('__contains__'.charAt(0)) {
                    case 'i':
                    case '_':
                        i = $b['__contains__'];
                }
                if (typeof i != "undefined") {
                    break;
                }
            }
        case false:
            if (typeof i == "undefined") {
                var _mro$, ga;
                if ($b['$inst'] === true) {
                    _meth_src = $b['__class__'];
                } else {
                    switch ('__contains__'.charAt(0)) {
                        case 'i':
                        case '_':
                            i = $b['__contains__'];
                    }
                    if (typeof i != "undefined") {
                        break;
                    }

                }
                if (typeof i == "undefined") {
                    for (var mro_i$ = 0; mro_i$ < mro$.length; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        i = _mro$['$dict']['__contains__'];
                        if (typeof i != "undefined") {
                            if (i !== {}['__contains__']) {
                                break;
                            }
                            i = [][1];
                        }
                        switch ('__contains__'.charAt(0)) {
                            case 'i':
                            case '_':
                                i = _mro$['__contains__'];
                        }
                        if (typeof i != "undefined") {
                            break;
                        }
                    }
                }
                if (typeof i == "undefined" && '__contains__' !== '__get__') {
                    for (var mro_i$ = 0; mro_i$ < mro$.length - 1; mro_i$++) {
                        _mro$ = mro$[mro_i$];
                        if (typeof _mro$['$dict'] == "undefined" || typeof _mro$['$dict']['__getattr__'] == "undefined") {
                            continue;
                        }
                        ga = _mro$['$dict']['__getattr__'];
                        if ($b['__class__']['$inst'] === false && $b['__class__'] !== @{{module}} && typeof $b != "undefined" && typeof $b['$inst'] != "undefined") {
                            switch (ga['__class__']) {
                                case @{{function}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $b['$inst'] === true ? $b['__class__'] : $b;
                                    _new_dst$['im_func'] = ga;
                                    _new_dst$['im_self'] = $b['$inst'] === true ? $b : null;
                                    ga = _new_dst$;
                                    break;
                                case @{{staticmethod}}:
                                    ga = ga['im_func'];
                                    break;
                                case @{{classmethod}}:
                                    var _new_dst$ = function ( ) {
                                        var args = Array.prototype.slice.call(arguments);
                                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                            if (arguments.callee['im_self'] !== null) {
                                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                            }
                                        }
                                        var a = @{{_getattr}}(arguments.callee, '__call__');
                                        if (typeof a == "undefined") {
                                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                                        }
                                        if (args.length >= 3) {
                                            var len = args.length;
                                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                            }
                                        }
                                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                    }
                                    _new_dst$['toString'] = function ( ) {
                                        try {
                                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                                        } catch (e) {
                                        }
                                        try {
                                            return "<" + this.__class__.__name__ + " instance>";
                                        } catch (e) {
                                        }
                                        return "<instance>";
                                    };
                                    _new_dst$['$inst'] = true;
                                    if (typeof @{{instancemethod}} == "undefined") {
                                        debugger;
                                    }
                                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                                        _new_dst$['__dict__'] = B$dict();
                                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                                    }
                                    _new_dst$['__class__'] = @{{instancemethod}};
                                    _new_dst$['im_class'] = $b['$inst'] === true ? $b['__class__'] : $b;
                                    _new_dst$['im_func'] = ga['im_func'];
                                    _new_dst$['im_self'] = $b['$inst'] === true ? $b['__class__'] : $b;
                                    ga = _new_dst$;
                                    break;
                                case @{{bool}}: // Some known to be non-descriptors
                                case @{{int}}:
                                case @{{long}}:
                                case @{{str}}:
                                    break;
                                default:
                                    // check for __get__ method in ga
                                    if (ga['$inst'] === true) {
                                        var get$ = @{{_getattr}}(ga, '__get__');
                                        if (typeof get$ != 'undefined') {
                                            ga = @{{fcall}}(this, null, get$, ga, $b, $b['__class__']);
                                        }
                                    }
                                    break;
                            }
                        }
                        @{{noraise}} = @{{AttributeError}};
                        i = @{{fcall}}(this, null, ga, _mro$, '__contains__');
                        @{{noraise}} = _noraise$;
                        if (i === @{{AttributeError}}) {
                            i = [][1];
                        }
                        // TODO : unbind i ?
                        break;
                    }
                }
            }
            break;
        default:
            i = $b['__contains__'];
            if (typeof i == "undefined" && typeof $b['$dict'] != "undefined") {
                i = $b['$dict']['__contains__'];
            }
    }
    if (typeof i != "undefined") {
        if (_meth_src['$inst'] === false && $b['__class__'] !== @{{module}} && typeof i != "undefined" && typeof i['$inst'] != "undefined") {
            switch (i['__class__']) {
                case @{{function}}:
                    var _new_dst$ = function ( ) {
                        var args = Array.prototype.slice.call(arguments);
                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                            if (arguments.callee['im_self'] !== null) {
                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                            }
                        }
                        var a = @{{_getattr}}(arguments.callee, '__call__');
                        if (typeof a == "undefined") {
                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                        }
                        if (args.length >= 3) {
                            var len = args.length;
                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                        }
                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                    }
                    _new_dst$['toString'] = function ( ) {
                        try {
                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                        } catch (e) {
                        }
                        try {
                            return "<" + this.__class__.__name__ + " instance>";
                        } catch (e) {
                        }
                        return "<instance>";
                    };
                    _new_dst$['$inst'] = true;
                    if (typeof @{{instancemethod}} == "undefined") {
                        debugger;
                    }
                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                        _new_dst$['__dict__'] = B$dict();
                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                    }
                    _new_dst$['__class__'] = @{{instancemethod}};
                    _new_dst$['im_class'] = $b['$inst'] === true ? $b['__class__'] : $b;
                    _new_dst$['im_func'] = i;
                    _new_dst$['im_self'] = $b['$inst'] === true ? $b : null;
                    i = _new_dst$;
                    break;
                case @{{staticmethod}}:
                    i = i['im_func'];
                    break;
                case @{{classmethod}}:
                    var _new_dst$ = function ( ) {
                        var args = Array.prototype.slice.call(arguments);
                        if (arguments.callee['__class__'] === @{{instancemethod}}) {
                            if (arguments.callee['im_self'] !== null) {
                                return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                            }
                        }
                        var a = @{{_getattr}}(arguments.callee, '__call__');
                        if (typeof a == "undefined") {
                            @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                        }
                        if (args.length >= 3) {
                            var len = args.length;
                            if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                            }
                        }
                        return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                    }
                    _new_dst$['toString'] = function ( ) {
                        try {
                            return @{{mcall}}(this, null, this, '__str__').valueOf();
                        } catch (e) {
                        }
                        try {
                            return "<" + this.__class__.__name__ + " instance>";
                        } catch (e) {
                        }
                        return "<instance>";
                    };
                    _new_dst$['$inst'] = true;
                    if (typeof @{{instancemethod}} == "undefined") {
                        debugger;
                    }
                    if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                        _new_dst$['__dict__'] = B$dict();
                        _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                    }
                    _new_dst$['__class__'] = @{{instancemethod}};
                    _new_dst$['im_class'] = $b['$inst'] === true ? $b['__class__'] : $b;
                    _new_dst$['im_func'] = i['im_func'];
                    _new_dst$['im_self'] = $b['$inst'] === true ? $b['__class__'] : $b;
                    i = _new_dst$;
                    break;
                case @{{bool}}: // Some known to be non-descriptors
                case @{{int}}:
                case @{{long}}:
                case @{{str}}:
                    break;
                default:
                    // check for __get__ method in i
                    if (i['$inst'] === true) {
                        var get$ = @{{_getattr}}(i, '__get__');
                        if (typeof get$ != 'undefined') {
                            i = @{{fcall}}(this, null, get$, i, $b, $b['__class__']);
                        }
                    }
                    break;
            }
        }
        return @{{fcall}}(this, null, i,  $b, $a).valueOf() ? @{{False}} : @{{True}};
    }
    var __iter__ = @{{iter}}($b);
    var $stopiter = @{{stopiter}}
    for (;;) {
        @{{stopiter}} = true;
        i = @{{mcall}}(this, null, __iter__, 'next');
        @{{stopiter}} = $stopiter;
        if (i === @{{StopIter}}) {
            return @{{True}};
        }
        if (@{{op_eq}}(i, $a)) {
            return @{{False}};
        }
    }

});

func(m$, null, f$, 'op_add', 1, ['x', 'y', 'i'], null, null, null, function($x, $y, $i) {
    if (typeof $x == 'string' && typeof $y == 'string') {
        return $new(@{{str}}, $x + $y);
    }
    if ($x !== null && $y !== null) {
        var m = $i === true ? '__iadd__' : '__add__';
        switch (($x.__number__ << 8) | $y.__number__) {
            case 0x0101:
            case 0x0102:
            case 0x0201:
            case 0x0104:
            case 0x0401:
                var x_v = $x.valueOf(), y_v = $y.valueOf();
                return $new(@{{float}}, x_v + y_v);
            case 0x0202:
                return @{{int}}['$dict'].__add__($x, $y);
            case 0x0204:
                return @{{long}}['$dict'].__add($new(@{{long}}, $x.__v), $y);
            case 0x0402:
                return @{{long}}['$dict'].__add($x, $new(@{{long}}, $y.__v));
            case 0x0404:
                return @{{long}}['$dict'].__add($x, $y);
        }
        if ($x['$inst'] === true && $y['$inst'] === true) {
            var op, v;
            op = @{{_getattr}}($x, m);
            if (typeof op != "undefined") {
                v = @{{fcall}}(this, null, op, $x, $y);
                if (v !== @{{NotImplemented}}) {
                    return v;
                }
            }
            if ($i !== true) {
                op = @{{_getattr}}($y, '__radd__');
                if (typeof op != "undefined") {
                    v = @{{mcall}}(this, null, $y, '__radd__', $x);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            } else {
                op = @{{_getattr}}($x, '__add__');
                if (typeof op != "undefined") {
                    v = @{{fcall}}(this, null, op, $x, $y);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            }
        }
        var x_v = $x.valueOf(), y_v = $y.valueOf();
        if (typeof x_v == 'number' && typeof y_v == 'number') {
            return $new(@{{float}}, x_v + y_v);
        }
    }
    @{{raise}}($new(@{{TypeError}}, B$str("unsupported operand type(s) for +: '" + @{{repr}}($x) + "', '" + @{{repr}}($y) + "'")));
});
func(m$, null, f$, 'op_sub', 1, ['x', 'y', 'i'], null, null, null, function($x, $y, $i) {
    if ($x !== null && $y !== null) {
        var m = $i === true ? '__isub__' : '__sub__';
        switch (($x.__number__ << 8) | $y.__number__) {
            case 0x0101:
            case 0x0102:
            case 0x0201:
            case 0x0104:
            case 0x0401:
                var x_v = $x.valueOf(), y_v = $y.valueOf();
                return $new(@{{float}}, x_v - y_v);
            case 0x0202:
                return @{{int}}['$dict'].__sub__($x, $y);
            case 0x0204:
                return @{{long}}['$dict'].__sub($new(@{{long}}, $x.__v), $y);
            case 0x0402:
                return @{{long}}['$dict'].__sub($x, $new(@{{long}}, $y.__v));
            case 0x0404:
                return @{{long}}['$dict'].__sub($x, $y);
        }
        if ($x['$inst'] === true && $y['$inst'] === true) {
            var op, v;
            op = @{{_getattr}}($x, m);
            if (typeof op != "undefined") {
                v = @{{fcall}}(this, null, op, $x, $y);
                if (v !== @{{NotImplemented}}) {
                    return v;
                }
            }
            if ($i !== true) {
                op = @{{_getattr}}($y, '__rsub__');
                if (typeof op != "undefined") {
                    v = @{{mcall}}(this, null, $y, '__rsub__', $x);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            } else {
                op = @{{_getattr}}($x, '__sub__');
                if (typeof op != "undefined") {
                    v = @{{fcall}}(this, null, op, $x, $y);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            }
        }
        var x_v = $x.valueOf(), y_v = $y.valueOf();
        if (typeof x_v == 'number' && typeof y_v == 'number') {
            return $new(@{{float}}, x_v - y_v);
        }
    }
    @{{raise}}($new(@{{TypeError}}, B$str("unsupported operand type(s) for -: '" + @{{repr}}($x) + "', '" + @{{repr}}($y) + "'")));
});
func(m$, null, f$, 'op_floordiv', 1, ['x', 'y', 'i'], null, null, null, function($x, $y, $i) {
    if ($y.valueOf() == 0) return @{{raise}}($new(@{{ZeroDivisionError}}, B$str('float divmod()')));
    if ($x !== null && $y !== null) {
        var m = $i === true ? '__ifloordiv__' : '__floordiv__';
        switch (($x.__number__ << 8) | $y.__number__) {
            case 0x0101:
            case 0x0102:
            case 0x0201:
            case 0x0104:
            case 0x0401:
                var x_v = $x.valueOf(), y_v = $y.valueOf();
                return $new(@{{float}}, Math.floor(x_v / y_v));
            case 0x0202:
                return @{{int}}['$dict'].__floordiv__($x, $y);
            case 0x0204:
                return @{{long}}['$dict'].__floordiv($new(@{{long}}, $x.__v), $y);
            case 0x0402:
                return @{{long}}['$dict'].__floordiv($x, $new(@{{long}}, $y.__v));
            case 0x0404:
                return @{{long}}['$dict'].__floordiv($x, $y);
        }
        if ($x['$inst'] === true && $y['$inst'] === true) {
            var op, v;
            op = @{{_getattr}}($x, m);
            if (typeof op != "undefined") {
                v = @{{fcall}}(this, null, op, $x, $y);
                if (v !== @{{NotImplemented}}) {
                    return v;
                }
            }
            if ($i !== true) {
                op = @{{_getattr}}($y, '__rfloordiv__');
                if (typeof op != "undefined") {
                    v = @{{mcall}}(this, null, $y, '__rfloordiv__', $x);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            } else {
                op = @{{_getattr}}($x, '__floordiv__');
                if (typeof op != "undefined") {
                    v = @{{fcall}}(this, null, op, $x, $y);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            }
        }
        var x_v = $x.valueOf(), y_v = $y.valueOf();
        if (typeof x_v == 'number' && typeof y_v == 'number') {
            return $new(@{{float}}, Math.floor(x_v / y_v));
        }
    }
    @{{raise}}($new(@{{TypeError}}, B$str("unsupported operand type(s) for //: '" + @{{repr}}($x) + "', '" + @{{repr}}($y) + "'")));
});
func(m$, null, f$, 'op_div', 1, ['x', 'y', 'i'], null, null, null, function($x, $y, $i) {
    if ($y.valueOf() == 0) return @{{raise}}($new(@{{ZeroDivisionError}}, B$str('float divmod()')));
    if ($x !== null && $y !== null) {
        var m = $i === true ? '__idiv__' : '__div__';
        switch (($x.__number__ << 8) | $y.__number__) {
            case 0x0101:
            case 0x0102:
            case 0x0201:
            case 0x0104:
            case 0x0401:
                var x_v = $x.valueOf(), y_v = $y.valueOf();
                return $new(@{{float}}, x_v / y_v);
            case 0x0202:
                return @{{int}}['$dict'].__div__($x, $y);
            case 0x0204:
                return @{{long}}['$dict'].__div($new(@{{long}}, $x.__v), $y);
            case 0x0402:
                return @{{long}}['$dict'].__div($x, $new(@{{long}}, $y.__v));
            case 0x0404:
                return @{{long}}['$dict'].__div($x, $y);
        }
        if ($x['$inst'] === true && $y['$inst'] === true) {
            var op, v;
            op = @{{_getattr}}($x, m);
            if (typeof op != "undefined") {
                v = @{{fcall}}(this, null, op, $x, $y);
                if (v !== @{{NotImplemented}}) {
                    return v;
                }
            }
            if ($i !== true) {
                op = @{{_getattr}}($y, '__rdiv__');
                if (typeof op != "undefined") {
                    v = @{{mcall}}(this, null, $y, '__rdiv__', $x);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            } else {
                op = @{{_getattr}}($x, '__div__');
                if (typeof op != "undefined") {
                    v = @{{fcall}}(this, null, op, $x, $y);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            }
        }
        var x_v = $x.valueOf(), y_v = $y.valueOf();
        if (typeof x_v == 'number' && typeof y_v == 'number') {
            return $new(@{{float}}, x_v / y_v);
        }
    }
    @{{raise}}($new(@{{TypeError}}, B$str("unsupported operand type(s) for /: '" + @{{repr}}($x) + "', '" + @{{repr}}($y) + "'")));
});
func(m$, null, f$, 'op_truediv', 1, ['x', 'y', 'i'], null, null, null, function($x, $y, $i) {
    if ($y.valueOf() == 0) return @{{raise}}($new(@{{ZeroDivisionError}}, B$str('float divmod()')));
    if ($x !== null && $y !== null) {
        var m = $i === true ? '__itruediv__' : '__truediv__';
        switch (($x.__number__ << 8) | $y.__number__) {
            case 0x0101:
            case 0x0102:
            case 0x0201:
            case 0x0104:
            case 0x0401:
                var x_v = $x.valueOf(), y_v = $y.valueOf();
                return $new(@{{float}}, x_v / y_v);
            case 0x0202:
                return @{{int}}['$dict'].__truediv__($x, $y);
            case 0x0204:
                return @{{long}}['$dict'].__truediv($new(@{{long}}, $x.__v), $y);
            case 0x0402:
                return @{{long}}['$dict'].__truediv($x, $new(@{{long}}, $y.__v));
            case 0x0404:
                return @{{long}}['$dict'].__truediv($x, $y);
        }
        if ($x['$inst'] === true && $y['$inst'] === true) {
            var op, v;
            op = @{{_getattr}}($x, m);
            if (typeof op != "undefined") {
                v = @{{fcall}}(this, null, op, $x, $y);
                if (v !== @{{NotImplemented}}) {
                    return v;
                }
            }
            if ($i !== true) {
                op = @{{_getattr}}($y, '__rtruediv__');
                if (typeof op != "undefined") {
                    v = @{{mcall}}(this, null, $y, '__rtruediv__', $x);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            } else {
                op = @{{_getattr}}($x, '__truediv__');
                if (typeof op != "undefined") {
                    v = @{{fcall}}(this, null, op, $x, $y);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            }
        }
        var x_v = $x.valueOf(), y_v = $y.valueOf();
        if (typeof x_v == 'number' && typeof y_v == 'number') {
            return $new(@{{float}}, x_v / y_v);
        }
    }
    @{{raise}}($new(@{{TypeError}}, B$str("unsupported operand type(s) for /: '" + @{{repr}}($x) + "', '" + @{{repr}}($y) + "'")));
});
func(m$, null, f$, 'op_mul', 1, ['x', 'y', 'i'], null, null, null, function($x, $y, $i) {
    if ($x !== null && $y !== null) {
        var m = $i === true ? '__imul__' : '__mul__';
        switch (($x.__number__ << 8) | $y.__number__) {
            case 0x0101:
            case 0x0102:
            case 0x0201:
            case 0x0104:
            case 0x0401:
                var x_v = $x.valueOf(), y_v = $y.valueOf();
                return $new(@{{float}}, x_v * y_v);
            case 0x0202:
                return @{{int}}['$dict'].__mul__($x, $y);
            case 0x0204:
                return @{{long}}['$dict'].__mul($new(@{{long}}, $x.__v), $y);
            case 0x0402:
                return @{{long}}['$dict'].__mul($x, $new(@{{long}}, $y.__v));
            case 0x0404:
                return @{{long}}['$dict'].__mul($x, $y);
        }
        if ($x['$inst'] === true && $y['$inst'] === true) {
            var op, v;
            op = @{{_getattr}}($x, m);
            if (typeof op != "undefined") {
                v = @{{fcall}}(this, null, op, $x, $y);
                if (v !== @{{NotImplemented}}) {
                    return v;
                }
            }
            if ($i !== true) {
                op = @{{_getattr}}($y, '__rmul__');
                if (typeof op != "undefined") {
                    v = @{{mcall}}(this, null, $y, '__rmul__', $x);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            } else {
                op = @{{_getattr}}($x, '__mul__');
                if (typeof op != "undefined") {
                    v = @{{fcall}}(this, null, op, $x, $y);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            }
        }
        var x_v = $x.valueOf(), y_v = $y.valueOf();
        if (typeof x_v == 'number' && typeof y_v == 'number') {
            return $new(@{{float}}, x_v * y_v);
        }
    }
    @{{raise}}($new(@{{TypeError}}, B$str("unsupported operand type(s) for *: '" + @{{repr}}($x) + "', '" + @{{repr}}($y) + "'")));
});
func(m$, null, f$, 'op_mod', 1, ['x', 'y', 'i'], null, null, null, function($x, $y, $i) {
    if ($x.__class__ == @{{str}}) {
        return @{{sprintf}}($x, $y);
    }
    if ($y.valueOf() == 0) return @{{raise}}($new(@{{ZeroDivisionError}}, B$str('float divmod()')));
    if ($x !== null && $y !== null) {
        var m = $i === true ? '__imod__' : '__mod__';
        switch (($x.__number__ << 8) | $y.__number__) {
            case 0x0101:
            case 0x0102:
            case 0x0201:
            case 0x0104:
            case 0x0401:
                var x_v = $x.valueOf(), y_v = $y.valueOf();
                return $new(@{{float}}, (x_v=x_v % y_v) < 0 && y_v > 0 ? x_v + y_v : x_v);
            case 0x0202:
                return @{{int}}['$dict'].__mod__($x, $y);
            case 0x0204:
                return @{{long}}['$dict'].__mod($new(@{{long}}, $x.__v), $y);
            case 0x0402:
                return @{{long}}['$dict'].__mod($x, $new(@{{long}}, $y.__v));
            case 0x0404:
                return @{{long}}['$dict'].__mod($x, $y);
        }
        if ($x['$inst'] === true && $y['$inst'] === true) {
            var op, v;
            op = @{{_getattr}}($x, m);
            if (typeof op != "undefined") {
                v = @{{fcall}}(this, null, op, $x, $y);
                if (v !== @{{NotImplemented}}) {
                    return v;
                }
            }
            if ($i !== true) {
                op = @{{_getattr}}($y, '__rmod__');
                if (typeof op != "undefined") {
                    v = @{{mcall}}(this, null, $y, '__rmod__', $x);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            } else {
                op = @{{_getattr}}($x, '__mod__');
                if (typeof op != "undefined") {
                    v = @{{fcall}}(this, null, op, $x, $y);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            }
        }
        var x_v = $x.valueOf(), y_v = $y.valueOf();
        if (typeof x_v == 'number' && typeof y_v == 'number') {
            return $new(@{{float}}, (x_v=x_v % y_v) < 0 && y_v > 0 ? x_v + y_v : x_v);
        }
    }
    @{{raise}}($new(@{{TypeError}}, B$str("unsupported operand type(s) for %: '" + @{{repr}}($x) + "', '" + @{{repr}}($y) + "'")));
});
func(m$, null, f$, 'op_pow', 1, ['x', 'y', 'i'], null, null, null, function($x, $y, $i) {
    if ($x !== null && $y !== null) {
        var m = $i === true ? '__ipow__' : '__pow__';
        switch (($x.__number__ << 8) | $y.__number__) {
            case 0x0101:
            case 0x0102:
            case 0x0201:
            case 0x0104:
            case 0x0401:
                var x_v = $x.valueOf(), y_v = $y.valueOf();
                return $new(@{{float}}, Math.pow(x_v, y_v));
            case 0x0202:
                return @{{int}}['$dict'].__pow__($x, $y);
            case 0x0204:
                return @{{long}}['$dict'].__pow($new(@{{long}}, $x.__v), $y);
            case 0x0402:
                return @{{long}}['$dict'].__pow($x, $new(@{{long}}, $y.__v));
            case 0x0404:
                return @{{long}}['$dict'].__pow($x, $y);
        }
        if ($x['$inst'] === true && $y['$inst'] === true) {
            var op, v;
            op = @{{_getattr}}($x, m);
            if (typeof op != "undefined") {
                v = @{{fcall}}(this, null, op, $x, $y);
                if (v !== @{{NotImplemented}}) {
                    return v;
                }
            }
            if ($i !== true) {
                op = @{{_getattr}}($y, '__rpow__');
                if (typeof op != "undefined") {
                    v = @{{mcall}}(this, null, $y, '__rpow__', $x);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            } else {
                op = @{{_getattr}}($x, '__pow__');
                if (typeof op != "undefined") {
                    v = @{{fcall}}(this, null, op, $x, $y);
                    if (v !== @{{NotImplemented}}) {
                        return v;
                    }
                }
            }
        }
        var x_v = $x.valueOf(), y_v = $y.valueOf();
        if (typeof x_v == 'number' && typeof y_v == 'number') {
            return $new(@{{float}}, Math.pow(x_v, y_v));
        }
    }
    @{{raise}}($new(@{{TypeError}}, B$str("unsupported operand type(s) for **: '" + @{{repr}}($x) + "', '" + @{{repr}}($y) + "'")));
});

func(m$, null, f$, 'op_bitand2', 1, ['x', 'y'], null, null, null, function($x, $y) {
    if ($x !== null && $y !== null) {
        switch (($x.__number__ << 8) | $y.__number__) {
            case 0x0202:
                if ($x['__class__'] === @{{int}}) {
                    return $x['__class__']['$dict']['__and__']($x, $y);
                }
                break
            case 0x0204:
                if ($y['__class__'] === @{{long}}) {
                    return $y['__class__']['$dict']['__rand__']($y, $new(@{{long}}, $x));
                }
                break
            case 0x0402:
                if ($x['__class__'] === @{{long}}) {
                    return $x['__class__']['$dict']['__and']($x, $new(@{{long}}, $y.__v));
                }
                break
            case 0x0404:
                if ($x['__class__'] === @{{long}}) {
                    return $x['__class__']['$dict']['__and']($x, $y);
                }
                break
        }
        var v = @{{_getattr}}($x, '__and__');
        if (typeof v != "undefined") {
            v = @{{fcall}}(this, null, v, $x, $y);
            if (v !== @{{NotImplemented}}) {
                return v;
            }
        }
        v = @{{_getattr}}($y, '__rand__');
        if (typeof v != "undefined") {
            v = @{{fcall}}(this, null, v, $y, $x);
            if (v !== @{{NotImplemented}}) {
                return v;
            }
        }
    }
    @{{raise}}($new(@{{TypeError}}, @{{sprintf}}("unsupported operand type(s) for &: '%r', '%r'", [$x, $y])));
});
func(m$, null, f$, 'op_bitand', 1, ['args'], null, null, null, function($args) {
    var a;
    if (args[0] !== null && args[1] !== null && args.length > 1) {
        var v, r, arg;
        v = args[0];
        for (var i = 1; i < args.length; i++) {
            arg = args[i]
            r = @{{_getattr}}(v, '__and__');
            if (typeof r != "undefined") {
                r = @{{fcall}}(this, null, r, v, arg);
                if (r !== @{{NotImplemented}}) {
                    v = r;
                    continue;
                }
            }
            r = @{{_getattr}}(arg, '__rand__');
            if (typeof r != "undefined") {
                r = @{{fcall}}(this, null, r, arg, v);
                if (r !== @{{NotImplemented}}) {
                    v = r;
                    continue;
                }
            }
            v = null;
            break;
        }
        if (v !== null) {
            return v;
        }
    }
    var msg = "unsupported operand type(s) for &: "
    for (var i = 0; i < args.length; i++) {
        msg += @{{repr}}(args[i]);
    }
    @{{raise}}($new(@{{TypeError}}, B$str(msg)));
});

func(m$, null, f$, 'op_bitor2', 1, ['x', 'y'], null, null, null, function($x, $y) {
    if ($x !== null && $y !== null) {
        switch (($x.__number__ << 8) | $y.__number__) {
            case 0x0202:
                if ($x['__class__'] === @{{int}}) {
                    return $x['__class__']['$dict']['__or__']($x, $y);
                }
                break
            case 0x0204:
                if ($y['__class__'] === @{{long}}) {
                    return $y['__class__']['$dict']['__ror__']($y, $new(@{{long}}, $x));
                }
                break
            case 0x0402:
                if ($x['__class__'] === @{{long}}) {
                    return $x['__class__']['$dict']['__or']($x, $new(@{{long}}, $y.__v));
                }
                break
            case 0x0404:
                if ($x['__class__'] === @{{long}}) {
                    return $x['__class__']['$dict']['__or']($x, $y);
                }
                break
        }
        var v = @{{_getattr}}($x, '__or__');
        if (typeof v != "undefined") {
            v = @{{fcall}}(this, null, v, $x, $y);
            if (v !== @{{NotImplemented}}) {
                return v;
            }
        }
        v = @{{_getattr}}($y, '__ror__');
        if (typeof v != "undefined") {
            v = @{{fcall}}(this, null, v, $y, $x);
            if (v !== @{{NotImplemented}}) {
                return v;
            }
        }
    }
    @{{raise}}($new(@{{TypeError}}, @{{sprintf}}("unsupported operand type(s) for |: '%r', '%r'", [$x, $y])));
});
func(m$, null, f$, 'op_bitor', 1, ['args'], null, null, null, function($args) {
    var a;
    if (args[0] !== null && args[1] !== null && args.length > 1) {
        var v, r, arg;
        v = args[0];
        for (var i = 1; i < args.length; i++) {
            arg = args[i]
            r = @{{_getattr}}(v, '__or__');
            if (typeof r != "undefined") {
                r = @{{fcall}}(this, null, r, v, arg);
                if (r !== @{{NotImplemented}}) {
                    v = r;
                    continue;
                }
            }
            r = @{{_getattr}}(arg, '__ror__');
            if (typeof r != "undefined") {
                r = @{{fcall}}(this, null, r, arg, v);
                if (r !== @{{NotImplemented}}) {
                    v = r;
                    continue;
                }
            }
            v = null;
            break;
        }
        if (v !== null) {
            return v;
        }
    }
    var msg = "unsupported operand type(s) for |: "
    for (var i = 0; i < args.length; i++) {
        msg += @{{repr}}(args[i]);
    }
    @{{raise}}($new(@{{TypeError}}, B$str(msg)));
});

func(m$, null, f$, 'op_bitxor2', 1, ['x', 'y'], null, null, null, function($x, $y) {
    if ($x !== null && $y !== null) {
        switch (($x.__number__ << 8) | $y.__number__) {
            case 0x0202:
                if ($x['__class__'] === @{{int}}) {
                    return $x['__class__']['$dict']['__xor__']($x, $y);
                }
                break
            case 0x0204:
                if ($y['__class__'] === @{{long}}) {
                    return $y['__class__']['$dict']['__rxor__']($y, $new(@{{long}}, $x));
                }
                break
            case 0x0402:
                if ($x['__class__'] === @{{long}}) {
                    return $x['__class__']['$dict']['__xor']($x, $new(@{{long}}, $y.__v));
                }
                break
            case 0x0404:
                if ($x['__class__'] === @{{long}}) {
                    return $x['__class__']['$dict']['__xor']($x, $y);
                }
                break
        }
        var v = @{{_getattr}}($x, '__xor__');
        if (typeof v != "undefined") {
            v = @{{fcall}}(this, null, v, $x, $y);
            if (v !== @{{NotImplemented}}) {
                return v;
            }
        }
        v = @{{_getattr}}($y, '__rxor__');
        if (typeof v != "undefined") {
            v = @{{fcall}}(this, null, v, $y, $x);
            if (v !== @{{NotImplemented}}) {
                return v;
            }
        }
    }
    @{{raise}}($new(@{{TypeError}}, @{{sprintf}}("unsupported operand type(s) for ^: '%r', '%r'", [$x, $y])));
});
func(m$, null, f$, 'op_bitxor', 1, ['args'], null, null, null, function($args) {
    var a;
    if (args[0] !== null && args[1] !== null && args.length > 1) {
        var v, r, arg;
        v = args[0];
        for (var i = 1; i < args.length; i++) {
            arg = args[i]
            r = @{{_getattr}}(v, '__xor__');
            if (typeof r != "undefined") {
                r = @{{fcall}}(this, null, r, v, arg);
                if (r !== @{{NotImplemented}}) {
                    v = r;
                    continue;
                }
            }
            r = @{{_getattr}}(arg, '__rxor__');
            if (typeof r != "undefined") {
                r = @{{fcall}}(this, null, r, arg, v);
                if (r !== @{{NotImplemented}}) {
                    v = r;
                    continue;
                }
            }
            v = null;
            break;
        }
        if (v !== null) {
            return v;
        }
    }
    var msg = "unsupported operand type(s) for ^: "
    for (var i = 0; i < args.length; i++) {
        msg += @{{repr}}(args[i]);
    }
    @{{raise}}($new(@{{TypeError}}, B$str(msg)));
});

func(m$, null, f$, 'op_bitlshift2', 1, ['x', 'y'], null, null, null, function($x, $y) {
    if ($x !== null && $y !== null) {
        switch (($x.__number__ << 8) | $y.__number__) {
            case 0x0202:
                if ($x['__class__'] === @{{int}}) {
                    return $x['__class__']['$dict']['__lshift__']($x, $y);
                }
                break
            case 0x0204:
                if ($y['__class__'] === @{{long}}) {
                    return $y['__class__']['$dict']['__rlshift__']($y, $new(@{{long}}, $x));
                }
                break
            case 0x0402:
                if ($x['__class__'] === @{{long}}) {
                    return $x['__class__']['$dict']['__lshift']($x, $new(@{{long}}, $y.__v));
                }
                break
            case 0x0404:
                if ($x['__class__'] === @{{long}}) {
                    return $x['__class__']['$dict']['__lshift']($x, $y);
                }
                break
        }
        var v = @{{_getattr}}($x, '__lshift__');
        if (typeof v != "undefined") {
            v = @{{fcall}}(this, null, v, $x, $y);
            if (v !== @{{NotImplemented}}) {
                return v;
            }
        }
        v = @{{_getattr}}($y, '__rlshift__');
        if (typeof v != "undefined") {
            v = @{{fcall}}(this, null, v, $y, $x);
            if (v !== @{{NotImplemented}}) {
                return v;
            }
        }
    }
    @{{raise}}($new(@{{TypeError}}, @{{sprintf}}("unsupported operand type(s) for <<: '%r', '%r'", [$x, $y])));
});
func(m$, null, f$, 'op_bitlshift', 1, ['args'], null, null, null, function($args) {
    var a;
    if (args[0] !== null && args[1] !== null && args.length > 1) {
        var v, r, arg;
        v = args[0];
        for (var i = 1; i < args.length; i++) {
            arg = args[i]
            r = @{{_getattr}}(v, '__lshift__');
            if (typeof r != "undefined") {
                r = @{{fcall}}(this, null, r, v, arg);
                if (r !== @{{NotImplemented}}) {
                    v = r;
                    continue;
                }
            }
            r = @{{_getattr}}(arg, '__rlshift__');
            if (typeof r != "undefined") {
                r = @{{fcall}}(this, null, r, arg, v);
                if (r !== @{{NotImplemented}}) {
                    v = r;
                    continue;
                }
            }
            v = null;
            break;
        }
        if (v !== null) {
            return v;
        }
    }
    var msg = "unsupported operand type(s) for <<: "
    for (var i = 0; i < args.length; i++) {
        msg += @{{repr}}(args[i]);
    }
    @{{raise}}($new(@{{TypeError}}, B$str(msg)));
});

func(m$, null, f$, 'op_bitrshift2', 1, ['x', 'y'], null, null, null, function($x, $y) {
    if ($x !== null && $y !== null) {
        switch (($x.__number__ << 8) | $y.__number__) {
            case 0x0202:
                if ($x['__class__'] === @{{int}}) {
                    return $x['__class__']['$dict']['__rshift__']($x, $y);
                }
                break
            case 0x0204:
                if ($y['__class__'] === @{{long}}) {
                    return $y['__class__']['$dict']['__rrshift__']($y, $new(@{{long}}, $x));
                }
                break
            case 0x0402:
                if ($x['__class__'] === @{{long}}) {
                    return $x['__class__']['$dict']['__rshift']($x, $new(@{{long}}, $y.__v));
                }
                break
            case 0x0404:
                if ($x['__class__'] === @{{long}}) {
                    return $x['__class__']['$dict']['__rshift']($x, $y);
                }
                break
        }
        var v = @{{_getattr}}($x, '__rshift__');
        if (typeof v != "undefined") {
            v = @{{fcall}}(this, null, v, $x, $y);
            if (v !== @{{NotImplemented}}) {
                return v;
            }
        }
        v = @{{_getattr}}($y, '__rrshift__');
        if (typeof v != "undefined") {
            v = @{{fcall}}(this, null, v, $y, $x);
            if (v !== @{{NotImplemented}}) {
                return v;
            }
        }
    }
    @{{raise}}($new(@{{TypeError}}, @{{sprintf}}("unsupported operand type(s) for <<: '%r', '%r'", [$x, $y])));
});
func(m$, null, f$, 'op_bitrshift', 1, ['args'], null, null, null, function($args) {
    var a;
    if (args[0] !== null && args[1] !== null && args.length > 1) {
        var v, r, arg;
        v = args[0];
        for (var i = 1; i < args.length; i++) {
            arg = args[i]
            r = @{{_getattr}}(v, '__rshift__');
            if (typeof r != "undefined") {
                r = @{{fcall}}(this, null, r, v, arg);
                if (r !== @{{NotImplemented}}) {
                    v = r;
                    continue;
                }
            }
            r = @{{_getattr}}(arg, '__rrshift__');
            if (typeof r != "undefined") {
                r = @{{fcall}}(this, null, r, arg, v);
                if (r !== @{{NotImplemented}}) {
                    v = r;
                    continue;
                }
            }
            v = null;
            break;
        }
        if (v !== null) {
            return v;
        }
    }
    var msg = "unsupported operand type(s) for <<: "
    for (var i = 0; i < args.length; i++) {
        msg += @{{repr}}(args[i]);
    }
    @{{raise}}($new(@{{TypeError}}, B$str(msg)));
});


// Some internal functions

function tplass(t, n) {
    if (t.__array.length != n) {
        if (t.__array.length > n) {
            @{{raise}}($new(@{{ValueError}}, B$str("too many values to unpack")));
        } else {
            @{{raise}}($new(@{{ValueError}}, B$str("need more than " + n + " values to unpack")));
        }
    }
    return t;
}
@{{tplass}} = tplass;

function _isJsInt(v) {
    if (typeof v == 'number') {
        if (v > 0) {
            return v == Math.floor(v);
        } else {
            return v == Math.ceil(v);
        }
    }
    return false;
}

function _typeof(obj) {
    if (typeof obj['__class__'] != 'undefined') {
        return obj['__class__']['__name__'].valueOf();
    }
    return typeof obj;
}

""")



########################################################################################



def __dynamic_load__(importName):
    global __nondynamic_modules__
    setCompilerOptions("noDebug")
    module = JS("""$pyjs.loaded_modules[@{{importName}}]""")
    if sys is None or dynamic is None or __nondynamic_modules__.has_key(importName):
        return module
    if JS("""typeof @{{module}} == "undefined" """):
        try:
            dynamic.ajax_import("lib/" + importName + ".__" + platform + "__.js")
            module = JS("""$pyjs.loaded_modules[@{{importName}}]""")
        except:
            pass
    if JS("""typeof @{{module}} == "undefined" """):
        try:
            dynamic.ajax_import("lib/" + importName + ".js")
            module = JS("""$pyjs.loaded_modules[@{{importName}}]""")
        except:
            pass
        if JS("""typeof @{{module}} == "undefined" """):
            __nondynamic_modules__[importName] = 1.0
    return module

class BaseException:

    def __init__(self, *args):
        self.args = args
        #JS("@{{self}}.toString = function() {return @{{mcall}}(null, null, this, '__str__');}")

    def __getitem__(self, index):
        return self.args[index]

    def __str__(self):
        args = self.args
        if len(args) is 0:
            return ''
        elif len(args) is 1:
            return str(args[0])
        return repr(args)

    def __repr__(self):
        if callable(self):
            return "<type '%s'>" % self.__name__
        return self.__name__ + repr(self.args)

class KeyboardInterrupt(BaseException):
    pass

class Exception(BaseException):
    pass

class StandardError(Exception):
    pass

class AssertionError(StandardError):
    pass

class GeneratorExit(Exception):
    pass

class TypeError(StandardError):
    pass

class AttributeError(StandardError):
    pass

class NameError(StandardError):
    pass

class ValueError(StandardError):
    pass

class ImportError(StandardError):
    pass

class LookupError(StandardError):
    pass

class RuntimeError(StandardError):
    pass

class ArithmeticError(StandardError):
    pass

class SystemError(StandardError):
    pass

class KeyError(LookupError):

    def __str__(self):
        if len(self.args) is 0:
            return ''
        elif len(self.args) is 1:
            return repr(self.args[0])
        return repr(self.args)

class IndexError(LookupError):
    pass

class NotImplementedError(RuntimeError):
    pass

class ZeroDivisionError(ArithmeticError):
    pass

class OverflowError(ArithmeticError):
    pass

class UndefinedValueError(ValueError):
    pass

class StopIteration(Exception):
    pass

# StopIteration is used to get out of an iteration loop
StopIter = StopIteration()

class TryElseException(Exception):
    pass

# The TryElse 'error' is used to implement the else in try-except-else
# (to raise an exception when there wasn't any)
TryElse = TryElseException()

empty_str = ""
empty_tuple = ()

def init():

    # There seems to be an bug in Chrome with accessing the message
    # property, on which an error is thrown
    # Hence the declaration of 'var message' and the wrapping in try..catch
    JS("""
@{{_errorMapping}} = function(err) {
    if (err instanceof(ReferenceError) || err instanceof(TypeError)) {
        var message = '';
        try {
            message = err.message;
        } catch ( e) {
        }
        return @{{AttributeError}}(message);
    }
    return err;
};
""")

def open(fname, mode='r'):
    raise NotImplementedError("open is not implemented in browsers")

def abs(a):
    if a < 0:
        return -a
    return a

def cmp(a, b):
    JS("""
    var a = @{{a}}, b = @{{b}};
    var av = a.valueOf(),
        bv = b.valueOf(),
        amro, bmro, f;
    if (typeof av == typeof bv) {
        switch (typeof av) {
            case 'number':
            case 'string':
            case 'boolean':
                return av == bv ? @{{int_zero}} : (av < bv ? @{{int_minus_one}} : @{{int_one}});
        }
    }
    if (av === null) {
        if (bv === null) return @{{int_zero}};
        return @{{int_minus_one}};
    }
    if (bv === null) {
        return @{{int_one}};
    }
    if (a['$inst'] === true) {
        if (b['$inst'] == true) {
            switch ((a.__number__ << 8)|b.__number__) {
                case 0x0101:
                case 0x0102:
                case 0x0201:
                case 0x0202:
                    // a and b are int and/or float
                    return a == b ? @{{int_zero}} : (a < b ? @{{int_minus_one}} : @{{int_one}});

                case 0x0100:
                case 0x0200:
                case 0x0400:
                    f = @{{_getattr}}($b, '__cmp__');
                    if (typeof f != "undefined") {
                        return @{{op_neg}}(@{{fcall}}(this, null, f, $b, $a));
                    }
                    return @{{int_minus_one}};
                case 0x0001:
                case 0x0002:
                case 0x0004:
                    f = @{{_getattr}}($a, '__cmp__');
                    if (typeof f != "undefined") {
                        return @{{fcall}}(this, null, f, $a, $b);
                    }
                    return @{{int_one}};
                case 0x0104:
                case 0x0204:
                    return @{{mcall}}(this, null, $new(@{{long}}, av), '__cmp__', b);
                case 0x0401:
                case 0x0402:
                    return @{{mcall}}(this, null, a, '__cmp__', $new(@{{long}}, bv));
                case 0x0404:
                    return @{{mcall}}(this, null, a, '__cmp__', b);
            }
            try {
                return @{{mcall}}(this, null, a, '__cmp__', b);
            } catch (e) {
            }
            if ($a === $b) return @{{int_zero}};
            if (a === b) return @{{int_zero}};
            if (typeof $a[$hash_id_name$] != 'undefined') {
                if (typeof $b[$hash_id_name$] != 'undefined') {
                    if ($a[$hash_id_name$] < $b[$hash_id_name$]) {
                        return @{{int_minus_one}};
                    }
                    if ($a[$hash_id_name$] > $b[$hash_id_name$]) {
                        return @{{int_one}};
                    }
                    return @{{int_zero}};
                }
                return @{{int_minus_one}};
            }
            if (typeof $b[$hash_id_name$] != 'undefined') {
                return @{{int_one}};
            }
            // Just do something consistent
            return a.__class__.__name__ < b.__class__.__name__ ? @{{int_minus_one}} : @{{int_one}};
        }
        return @{{int_minus_one}};
    } else if (b['$inst'] === true) {
        return @{{int_minus_one}};
    } else if (a['$inst'] === false && b['$inst'] === false) {
        if (a === b) return @{{int_zero}};
        // Just do something consistent
        return a.__class__.__name__ < b.__class__.__name__ ? @{{int_minus_one}} : @{{int_one}};
    }
    if (a == b) return @{{int_zero}};
    if (a > b) return @{{int_one}};
    return @{{int_minus_one}};
    """)


class NotImplementedType(object):
    def __repr__(self):
        return "<type 'NotImplementedType'>"
    def __str__(self):
        self.__repr__()
    def toString(self):
        self.__repr__()
NotImplemented = NotImplementedType()

JS("""
var $iter_array = function (l) {
    this.__array = l;
    this.i = -1;
};
$iter_array.prototype.next = function (noStop) {
    if (++this.i == this.__array.length) {
        if (noStop === true) {
            return;
        }
        throw @{{StopIteration}};
    }
    return this.__array[this.i];
};
$iter_array.prototype.__iter__ = function ( ) {
    return this;
};
var $reversed_iter_array = function (l) {
    this.___array = l;
    this.i = l.length;
};
$reversed_iter_array.prototype.next = function (noStop) {
    if (--this.i == -1) {
        if (noStop === true) {
            return;
        }
        throw @{{StopIteration}};
    }
    return this.___array[this.i];
};
$reversed_iter_array.prototype.__iter__ = function ( ) {
    return this;
};
//$reversed_iter_array.prototype.$genfunc = $reversed_iter_array.prototype.next;
var $enumerate_array = function (l) {
    this.array = l;
    this.i = -1;
    this.tuple = $new(@{{tuple}}, [@{{int_zero}}, B$str("")]);
    this.tuple = @{{tuple}}.__call__(foo);
    this.tuple = @{{tuple}}.__call__([@{{int}}.__call__(0), B$str("")]);
    this.tl = this.tuple.__array;
};
$enumerate_array.prototype.next = function (noStop, reuseTuple) {
    if (++this.i == this.array.length) {
        if (noStop === true) {
            return;
        }
        throw @{{StopIteration}};
    }
    this.tl[1] = this.array[this.i];
    if (this.tl[0].__number__ == 0x01) {
        this.tl[0] = this.i;
    } else {
        this.tl[0] = new @{{int}}(this.i);
    }
    return reuseTuple === true ? this.tuple : @{{tuple}}(this.tl);
};
$enumerate_array.prototype.__iter__ = function ( ) {
    return this;
};
$enumerate_array.prototype.$genfunc = $enumerate_array.prototype.next;
""")
# NOTE: $genfunc is defined to enable faster loop code


class slice(object):

    def __init__(self, start, *args):
        if len(args) == 0:
            self.start = None
            self.stop = start
        else:
            self.start = start
            self.stop = args[0]
        if len(args) == 2:
            self.step = args[1]
        else:
            self.step = None

    def indices(self, n):
        step = 1 if self.step is None else self.step
        if step > 0:
            start = 0 if self.start is None else self.start
            stop = n if self.stop is None else self.stop
            if start > n:
                start = n
            elif start < 0:
                start = 0
            if stop < 0:
                stop += n
                if stop < start:
                    stop = start
            elif stop > n:
                stop = n
        else:
            start = n - 1 if self.start is None else self.start
            stop = -1 if self.stop is None else self.stop
            if stop > 0:
                if stop > start:
                    stop += n
                    if stop > start:
                        stop = start
            else:
                if start > n:
                    start = n - 1
                if stop <= -n:
                    stop += n
                    if stop < -1:
                        stop = -1
        return (start, stop, step)

    def __str__(self):
        return "slice(%s, %s, %s)" % (self.start, self.stop, self.step)

    def __repr__(self):
        return "slice(%s, %s, %s)" % (self.start, self.stop, self.step)

    def __hash__(self):
        raise TypeError("unhashable type")

    def __cmp__(self, y):
        a_start = 0 if self.start is None else self.start
        a_step = 1 if self.step is None else self.step
        b_start = 0 if y.start is None else y.start
        b_step = 1 if y.step is None else y.step
        if a_start < b_start:
            return -1
        if a_start > b_start:
            return 1
        if self.stop is not y.stop:
            if self.stop is None:
                return 1
            if y.stop is None:
                return -1
            if self.stop < y.stop:
                return -1
            return 1
        if a_step < b_step:
            return -1
        if a_step > b_step:
            return 1
        return 0

    # finally add builtin __slots__ for slice
    JS("""f$['__slots__'] = ['start', 'stop', 'step'];""")


class list(object):

    __new__ = JS("""function(cls, value) {
        var new_list = function ( ) {
            var args = Array.prototype.slice.call(arguments);
            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                if (arguments.callee['im_self'] !== null) {
                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                }
            }
            var a = @{{_getattr}}(arguments.callee, '__call__');
            if (typeof a == "undefined") {
                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
            }
            if (args.length >= 3) {
                var len = args.length;
                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                }
            }
            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
        }
        new_list['toString'] = function ( ) {
            try {
                return @{{mcall}}(this, null, this, '__str__').valueOf();
            } catch (e) {
            }
            try {
                return "<" + this.__class__.__name__ + " instance>";
            } catch (e) {
            }
            return "<instance>";
        };
        new_list['$inst'] = true;
        if (typeof cls == "undefined") {
            debugger;
        }
        if (typeof cls['__slots__'] == "undefined" || cls['__slots__'].length > 0) {
            new_list['__dict__'] = B$dict();
            new_list['$dict'] = new_list['__dict__']['__object'];
        }
        new_list['__class__'] = cls;
        new_list['__array'] = [];
        new_list['valueOf'] = function() {return this.__array;};
        new_list['toString'] = function() {return this['__class__']['$dict']['__str__'](this).valueOf();};
        return new_list;
    }""")

    __init__ = tuple.__init__


    def __hash__(self):
        raise TypeError("list objects are unhashable")

    def append(self, item):
        JS("""@{{self}}.__array[@{{self}}.__array.length] = @{{item}};""")

    # extend in place, just in case there's somewhere a shortcut to self.__array
    def extend(self, data):
        # Transform data into an array and append to self.__array
        JS("""
        if (@{{data}} === null) {
            @{{raise}}($new(@{{TypeError}}, B$str("'NoneType' is not iterable")));
        }
        if (@{{data}} instanceof Array) {
        } else if (@{{data}}.__array instanceof Array) {
            @{{data}} = @{{data}}.__array;
        } else if (typeof @{{data}}.__iter__ == 'function') {
            if (typeof @{{data}}.__array == 'object') {
                @{{data}} = @{{data}}.__array;
            } else {
                var iter = @{{data}}.__iter__();
                if (typeof iter.__array == 'object') {
                    @{{data}} = iter.__array;
                }
                @{{data}} = [];
                var item, i = 0;
                if (typeof iter.$genfunc == 'function') {
                    while (typeof (item=iter.next(true)) != "undefined") {
                        @{{data}}[i++] = item;
                    }
                } else {
                    try {
                        while (true) {
                            @{{data}}[i++] = iter.next();
                        }
                    }
                    catch (e) {
                        if (e.__name__ != 'StopIteration') throw e;
                    }
                }
            }
        } else {
            @{{raise}}($new(@{{TypeError}}, B$str("'" + @{{repr}}(@{{data}}) + "' is not iterable")));
        }
        var l = @{{self}}.__array;
        var j = @{{self}}.__array.length;
        var n = @{{data}}.length, i = 0;
        while (i < n) {
            l[j++] = @{{data}}[i++];
        }
        """)

    def remove(self, value):
        index = self.index(value)
        JS("""
        var index = @{{index}}.valueOf();
        if (index<0) {
            @{{raise}}($new(@{{ValueError}}, B$str("list.remove(x): x not in list")));
        }
        @{{self}}.__array.splice(index, 1);
        return true;
        """)

    count = tuple.count

    def index(self, value, _start=0):
        JS("""
        var start = @{{_start}}.valueOf();
        /* if (typeof valueXXX == 'number' || typeof valueXXX == 'string') {
            start = selfXXX.__array.indexOf(valueXXX, start);
            if (start >= 0)
                return start;
        } else */ {
            var len = @{{self}}.__array.length >>> 0;

            start = (start < 0)
                    ? Math.ceil(start)
                    : Math.floor(start);
            if (start < 0)
                start += len;

            for (; start < len; start++) {
                if ( /*start in selfXXX.__array && */
                    @{{cmp}}(@{{self}}.__array[start], @{{value}}) === @{{int_zero}})
                    return $new(@{{int}}, start);
            }
        }
        """)
        raise ValueError("list.index(x): x not in list")

    def insert(self, index, value):
        JS("""    var a = @{{self}}.__array; @{{self}}.__array=a.slice(0, @{{index}}).concat(@{{value}}, a.slice(@{{index}}));""")

    def pop(self, _index = -1):
        JS("""
        var index = @{{_index}}.valueOf();
        if (index<0) index += @{{self}}.__array.length;
        if (index < 0 || index >= @{{self}}.__array.length) {
            if (@{{self}}.__array.length == 0) {
                @{{raise}}($new(@{{IndexError}}, B$str("pop from empty list")));
            }
            @{{raise}}($new(@{{IndexError}}, B$str("pop index out of range")));
        }
        var a = @{{self}}.__array[index];
        @{{self}}.__array.splice(index, 1);
        return a;
        """)

    def __cmp__(self, l):
        if not isinstance(l, list):
            return -1
        JS("""
        var n1 = @{{self}}.__array.length,
            n2 = @{{l}}.__array.length,
            a1 = @{{self}}.__array,
            a2 = @{{l}}.__array,
            n, c;
        n = (n1 < n2 ? n1 : n2);
        for (var i = 0; i < n; i++) {
            c = @{{cmp}}(a1[i], a2[i]);
            if (c !== @{{int_zero}}) return c;
        }
        if (n1 < n2) return @{{int_minus_one}};
        if (n1 > n2) return @{{int_one}};
        return @{{int_zero}};""")

    def __getslice__(self, lower, upper):
        JS("""
        var lower = @{{lower}}.valueOf() || 0,
            upper = @{{upper}}.valueOf() === null ? @{{self}}.__array.length : @{{upper}}.valueOf();
        return @{{list}}(@{{self}}.__array.slice(lower, upper));
        """)

    def __delslice__(self, lower, upper):
        JS("""
        var lower = @{{lower}}.valueOf() || 0,
            upper = @{{upper}}.valueOf() === null ? @{{self}}.__array.length : @{{upper}}.valueOf(),
            n = upper - lower;
        if (n > 0) @{{self}}.__array.splice(lower, n);
        """)
        return None

    def __setslice__(self, lower, upper, data):
        self.__delslice__(lower, upper)
        tail = self.__getslice__(lower, None)
        self.__delslice__(lower, None)
        self.extend(data)
        self.extend(tail)
        return None

    __getitem__ = tuple.__getitem__

    def __setitem__(self, _index, value):
        JS("""
        if (@{{isinstance}}(@{{_index}}, [@{{int}}, @{{long}}]) === T$) {
            var index = @{{_index}}.valueOf();
            if (index < 0) index += @{{self}}.__array.length;
            if (index < 0 || index >= @{{self}}.__array.length) {
                @{{raise}}($new(@{{IndexError}}, B$str("list assignment index out of range")));
            }
            @{{self}}.__array[index]=@{{value}};
            return N$
        }
        if (@{{isinstance}}(@{{_index}}, [@{{slice}}]) === T$) {
            var start = @{{_index}}['$dict']['start'].valueOf(),
                stop = @{{_index}}['$dict']['stop'].valueOf(),
                step = @{{_index}}['$dict']['step'].valueOf(),
                __array = [],
                _stopiter = @{{stopiter}},
                iter, next, i, k, v, n_todo, n_done = 0;
            if (start === null) start = 0;
            if (stop === null || stop > $self.__array.length) stop = $self.__array.length;
            if (step === null) step = 1;
            if (step == 1) {
                return @{{self}}['__class__']['$dict']['__setslice__'](@{{self}}, $new(@{{int}}, start), $new(@{{int}}, stop), @{{value}});
            }
            debugger; // rest not tested
            n_todo = Math.floor((stop - start)/step);
            iter = @{{fcall}}(this, null, @{{iter}}, null, @{{value}});
            next = @{{getattr}}(iter, 'next');
            for (;;) {
                @{{stopiter}} = true;
                v = @{{fcall}}(this, null, next, iter);
                @{{stopiter}} = _stopiter;
                if (v === @{{StopIter}}) {
                    break;
                }
                __array.append(v);
            }
            if (n_todo != __array.length) {
                return @{{raise}}($new(@{{ValueError}}, B$sttr("attempt to assign sequence of size " + __array.length + " to extended slice of size " + n_todo)));
            }
            for (i = 0; start < stop; start += step, i++) {
                @{{self}}.__array[start] = __array[i];
            }
            return B$tuple(__array);
        }
        @{{raise}}($new(@{{TypeError}}, B$str(_typeof(@{{self}}) + " indices must be integers, not " + _typeof(@{{index}}))));
        """)

    def __delitem__(self, _index):
        JS("""
        var index = @{{_index}}.valueOf();
        if (index < 0) index += @{{self}}.__array.length;
        if (index < 0 || index >= @{{self}}.__array.length) {
            @{{raise}}($new(@{{IndexError}}, B$str("list assignment index out of range")));
        }
        @{{self}}.__array.splice(index, 1);
        """)

    def __len__(self):
        return JS("""$new(@{{int}}, @{{self}}.__array.length)""")

    def __contains__(self, value):
        try:
            self.index(value)
        except ValueError:
            return False
        return True

    def __iter__(self):
        return listiterator(self)

    def __reversed__(self):
        return listreverseiterator(self)

    def __enumerate__(self):
        return JS("new $enumerate_array(@{{self}}.__array)")

    def reverse(self):
        JS("""@{{self}}.__array.reverse();""")

    def sort(self, cmp_=None, key=None, reverse=False):
        if cmp_ is None:
            cmp_ = cmp
        if key and reverse:
            def sort(a, b):
                v = -cmp_(key(a), key(b))
                return JS("@{{v}}.__v")
        elif key:
            def sort(a, b):
                v = cmp_(key(a), key(b))
                return JS("@{{v}}.__v")
        elif reverse:
            def sort(a, b):
                v = -cmp_(a, b)
                return JS("@{{v}}.__v")
        else:
            def sort(a, b):
                v = cmp_(a, b)
                return JS("@{{v}}.__v")
        JS("@{{self}}.__array.sort(@{{sort}})")

    def getArray(self):
        """
        Access the javascript Array that is used internally by this list
        """
        return self.__array

    def __str__(self):
        JS("""
        var s = "[";
        for (var i=0; i < @{{self}}.__array.length; i++) {
            s += @{{repr}}(@{{self}}.__array[i]);
            if (i < @{{self}}.__array.length - 1)
                s += ", ";
        }
        s += "]";
        return B$str(s);
        """)

    def __repr__(self):
        JS("""
        var s = "[";
        for (var i=0; i < @{{self}}.__array.length; i++) {
            s += @{{repr}}(@{{self}}.__array[i]);
            if (i < @{{self}}.__array.length - 1)
                s += ", ";
        }
        s += "]";
        return B$str(s);
        """)

    def __add__(self, y):
        if not isinstance(y, list):
            raise TypeError("can only concatenate list to list")
        return list(self.__array.concat(y.__array))

    def __mul__(self, n):
        if not JS("@{{n}} !== null && @{{n}}.__number__ && (@{{n}}.__number__ != 0x01 || isFinite(@{{n}}))"):
            raise TypeError("can't multiply sequence by non-int")
        a = []
        while n:
            n -= 1
            a.extend(JS("@{{self}}.__array"))
        return a

    def __rmul__(self, n):
        return self.__mul__(n)

    # finally add builtin __slots__ for list
    JS("""f$['__slots__'] = [];""")


# OK. I'm too lazy to implement dict.update() in javascript.
# Therefore it's added here.
def update(self, *args, **kwargs):
    if args:
        if len(args) > 1:
            raise TypeError("update expected at most 1 arguments, got %d" % len(args))
        d = args[0]
        if hasattr(d, "iteritems"):
            for k,v in d.iteritems():
                self[k] = v
        elif hasattr(d, "keys"):
            for k in d:
                self[k] = d[k]
        else:
            for k, v in d:
                self[k] = v
    if kwargs:
        for k,v in kwargs.iteritems():
            self[k] = v
dict.update = update
del update

def globals(obj):
    o = JS("{}")
    JS("""
    for (k in @{{obj}}) {
        if (@{{obj}}[k] != "undefined" && @{{obj}}[k] !== B$[k]) {
            @{{o}}[k] = @{{obj}}[k];
        }
    }""")
    d = JS("B$dict(@{{o}}, true)")
    JS("@{{d}}.__object = @{{obj}}")
    def globals():
        return d
    return globals

def locals(obj):
    o = JS("{}")
    JS("""
    for (k in @{{obj}}) {
        if (typeof @{{obj}}[k] != "undefined") {
            @{{o}}[k] = @{{obj}}[k];
        }
    }""")
    d = JS("B$dict(@{{o}}, true)")
    JS("@{{d}}.__object = @{{obj}}")
    def locals():
        return d
    return locals



class set(object):
    def __init__(self, _data=None):
        """ Transform data into an array with [key,value] and add set
            self.__object
            Input data can be Array(key, val), iteratable (key,val) or
            Object/Function
        """
        JS("""
        var data = @{{_data}} === N$ ? [] : @{{_data}};
        if (@{{isSet}}(data)) {
            @{{self}}.__object = {};
            var selfObj = @{{self}}.__object,
                dataObj = data.__object;
            for (var sVal in dataObj) {
                selfObj[sVal] = dataObj[sVal];
            }
            return N$;
        }
        var item,
            i,
            n,
            selfObj = @{{self}}.__object = {};

        if (@{{!data}} instanceof Array) {
            // data is already an Array.
            // We deal with the Array of data after this if block.
        }

        // We may have some other set-like thing with __object
        else if (typeof @{{!data}}.__object == 'object') {
            var dataObj = @{{!data}}.__object;
            for (var sKey in dataObj) {
                selfObj[sKey] = dataObj[sKey];
            }
            return N$;
        } else {
            var iter = @{{fcall}}(this, null, @{{iter}}, null, data),
                next = @{{getattr}}(iter, 'next'),
                stopiter = @{{stopiter}},
                v;
            data = [];
            for (var i = 0;; i++) {
                @{{stopiter}} = true;
                v = @{{fcall}}(this, null, next, iter);
                @{{stopiter}} = stopiter;
                if (v === @{{StopIter}}) {
                    break;
                }
                data[i] = v;
            }
        }
        // Assume uniform array content...
        if ((n = @{{!data}}.length) == 0) {
            return N$;
        }
        i = n-1;
        do {
            item = @{{!data}}[i];
            selfObj[@{{hash}}(item)] = item;
        }
        while (i--);
        return N$;
        """)

    def __cmp__(self, other):
        # We (mis)use cmp here for the missing __gt__/__ge__/...
        # if self == other : return 0
        # if self is subset of other: return -1
        # if self is superset of other: return 1
        # else return None
        if not isSet(other):
            return None
            #other = frozenset(other)
        JS("""
        var selfObj = @{{self}}.__object,
            otherObj = @{{other}}.__object,
            selfMismatch = false,
            otherMismatch = false;
        if (selfObj === otherObj) {
            @{{raise}}($new(@{{TypeError}}, B$str("Set operations must use two sets.")));
            }
        for (var sVal in selfObj) {
            if (!(sVal in otherObj)) {
                selfMismatch = true;
                break;
            }
        }
        for (var sVal in otherObj) {
            if (!(sVal in selfObj)) {
                otherMismatch = true;
                break;
            }
        }
        if (selfMismatch && otherMismatch) return N$
        if (selfMismatch) return @{{int_one}};
        if (otherMismatch) return @{{int_minus_one}};
        return @{{int_zero}};
""")

    def __contains__(self, value):
        JS("""
        if (@{{isSet}}(@{{value}}) == 1) {
            // An instance of set
            // Use frozenset hash
            var hashes = new Array(),
                obj = @{{self}}.__object,
                i = 0;
            for (var v in obj) {
                hashes[i++] = v;
            }
            hashes.sort();
            var h = hashes.join("|");
            return (h in obj);
        }
        return @{{hash}}(@{{value}}) in @{{self}}.__object ? @{{True}} : @{{False}};
""")

    def __hash__(self):
        raise TypeError("set objects are unhashable")

    def __iter__(self):
        JS("""
        var items = new Array(),
            i = 0,
            obj = @{{self}}.__object;
        for (var key in obj) {
            items[i++] = obj[key];
        }
        return new $iter_array(items);
        """)

    def __len__(self):
        size=0.0
        JS("""
        for (var i in @{{self}}.__object) @{{size}}++;
        """)
        return int(size)

    #def __str__(self):
    #    return self.__repr__()
    #See monkey patch at the end of the set class definition

    def __repr__(self):
        if callable(self):
            return "<type '%s'>" % self.__name__
        JS("""
        var values = new Array();
        var i = 0,
            obj = @{{self}}.__object,
            s = @{{self}}['__class__']['__name__'] + "([";
        for (var sVal in obj) {
            values[i++] = @{{repr}}(obj[sVal]);
        }
        s += values.join(", ");
        s += "])";
        return B$str(s);
        """)

    def __and__(self, other):
        """ Return the intersection of two sets as a new set.
            only available under --number-classes
        """
        if not isSet(other):
            return NotImplemented
        return self.intersection(other)

    def __or__(self, other):
        """ Return the union of two sets as a new set..
            only available under --number-classes
        """
        if not isSet(other):
            return NotImplemented
        return self.union(other)

    def __xor__(self, other):
        """ Return the symmetric difference of two sets as a new set..
            only available under --number-classes
        """
        if not isSet(other):
            return NotImplemented
        return self.symmetric_difference(other)

    def  __sub__(self, other):
        """ Return the difference of two sets as a new Set..
            only available under --number-classes
        """
        if not isSet(other):
            return NotImplemented
        return self.difference(other)

    def add(self, value):
        JS("""@{{self}}.__object[@{{hash}}(@{{value}})] = @{{value}};""")
        return None

    def clear(self):
        JS("""@{{self}}.__object = {};""")
        return None

    def copy(self):
        new_set = set()
        JS("""
        var obj = @{{new_set}}.__object,
            selfObj = @{{self}}.__object;
        for (var sVal in selfObj) {
            obj[sVal] = selfObj[sVal];
        }
""")
        return new_set

    def difference(self, other):
        """ Return the difference of two sets as a new set.
            (i.e. all elements that are in this set but not the other.)
        """
        if not isSet(other):
            other = frozenset(other)
        new_set = set()
        JS("""
        var obj = @{{new_set}}.__object,
            selfObj = @{{self}}.__object,
            otherObj = @{{other}}.__object;
        for (var sVal in selfObj) {
            if (!(sVal in otherObj)) {
                obj[sVal] = selfObj[sVal];
            }
        }
""")
        return new_set

    def difference_update(self, other):
        """ Remove all elements of another set from this set.
        """
        if not isSet(other):
            other = frozenset(other)
        JS("""
        var selfObj = @{{self}}.__object,
            otherObj = @{{other}}.__object;
        for (var sVal in otherObj) {
            if (sVal in selfObj) {
                delete selfObj[sVal];
            }
        }
""")
        return None

    def discard(self, value):
        if isSet(value) == 1:
            value = frozenset(value)
        JS("""delete @{{self}}.__object[@{{hash}}(@{{value}})];""")
        return None

    def intersection(self, other):
        """ Return the intersection of two sets as a new set.
            (i.e. all elements that are in both sets.)
        """
        if not isSet(other):
            other = frozenset(other)
        new_set = set()
        JS("""
        var obj = @{{new_set}}.__object,
            selfObj = @{{self}}.__object,
            otherObj = @{{other}}.__object;
        for (var sVal in selfObj) {
            if (sVal in otherObj) {
                obj[sVal] = selfObj[sVal];
            }
        }
""")
        return new_set

    def intersection_update(self, other):
        """ Update a set with the intersection of itself and another.
        """
        if not isSet(other):
            other = frozenset(other)
        JS("""
        var selfObj = @{{self}}.__object,
            otherObj = @{{other}}.__object;
        for (var sVal in selfObj) {
            if (!(sVal in otherObj)) {
                delete selfObj[sVal];
            }
        }
""")
        return None

    def isdisjoint(self, other):
        """ Return True if two sets have a null intersection.
        """
        if not isSet(other):
            other = frozenset(other)
        JS("""
        var selfObj = @{{self}}.__object,
            otherObj = @{{other}}.__object;
        for (var sVal in selfObj) {
            if (typeof otherObj[sVal] != "undefined") {
                return @{{False}};
            }
        }
        for (var sVal in otherObj) {
            if (typeof selfObj[sVal] != "undefined") {
                return @{{False}};
            }
        }
""")
        return True

    def issubset(self, other):
        if not isSet(other):
            other = frozenset(other)
        v = self.__cmp__(other)
        if v is None:
            return False
        return v < 0
        return JS("@{{v}}.__v < 0 ? @{{True}} : @{{False}}")
        return JS("@{{self}}.__cmp__(@{{other}}).valueOf() < 0 ? @{{True}} : @{{False}}")

    def issuperset(self, other):
        if not isSet(other):
            other = frozenset(other)
        v = self.__cmp__(other)
        if v is None:
            return False
        return v >= 0
        return JS("@{{v}}.valueOf()|1 == 1 ? @{{True}} : @{{False}}")
        return JS("(@{{self}}.__cmp__(@{{other}}).valueOf()|1) == 1 ? @{{True}} : @{{False}}")

    def pop(self):
        JS("""
        for (var sVal in @{{self}}.__object) {
            var value = @{{self}}.__object[sVal];
            delete @{{self}}.__object[sVal];
            return value;
        }
        """)
        raise KeyError("pop from an empty set")

    def remove(self, value):
        JS("""
        var val = @{{isSet}}(@{{value}}) == 1 ? @{{frozenset}}(@{{value}}) : @{{value}};
        var h = @{{hash}}(val);
        if (!(h in @{{self}}.__object)) {
            return @{{raise}}($new(@{{KeyError}}, @{{value}}));
        }
        delete @{{self}}.__object[h];
        """)

    def symmetric_difference(self, other):
        """ Return the symmetric difference of two sets as a new set.
            (i.e. all elements that are in exactly one of the sets.)
        """
        if not isSet(other):
            other = frozenset(other)
        new_set = set()
        JS("""
        var obj = @{{new_set}}.__object,
            selfObj = @{{self}}.__object,
            otherObj = @{{other}}.__object;
        for (var sVal in selfObj) {
            if (typeof otherObj[sVal] == "undefined") {
                obj[sVal] = selfObj[sVal];
            }
        }
        for (var sVal in otherObj) {
            if (typeof selfObj[sVal] == "undefined") {
                obj[sVal] = otherObj[sVal];
            }
        }
""")
        return new_set

    def symmetric_difference_update(self, other):
        """ Update a set with the symmetric difference of itself and another.
        """
        if not isSet(other):
            other = frozenset(other)
        JS("""
        var obj = new Object(),
            selfObj = @{{self}}.__object,
            otherObj = @{{other}}.__object;
        for (var sVal in selfObj) {
            if (typeof otherObj[sVal] == "undefined") {
                obj[sVal] = selfObj[sVal];
            }
        }
        for (var sVal in otherObj) {
            if (typeof selfObj[sVal] == "undefined") {
                obj[sVal] = otherObj[sVal];
            }
        }
        @{{self}}.__object = obj;
""")
        return None

    def union(self, other):
        """ Return the union of two sets as a new set.
            (i.e. all elements that are in either set.)
        """
        new_set = set()
        if not isSet(other):
            other = frozenset(other)
        JS("""
        var obj = @{{new_set}}.__object,
            selfObj = @{{self}}.__object,
            otherObj = @{{other}}.__object;
        for (var sVal in selfObj) {
            obj[sVal] = selfObj[sVal];
        }
        for (var sVal in otherObj) {
            if (!(sVal in selfObj)) {
                obj[sVal] = otherObj[sVal];
            }
        }
""")
        return new_set

    def update(self, data):
        if not isSet(data):
            data = frozenset(data)
        JS("""
        var selfObj = @{{self}}.__object,
            dataObj = @{{data}}.__object;
        for (var sVal in dataObj) {
            if (!(sVal in selfObj)) {
                selfObj[sVal] = dataObj[sVal];
            }
        }
        """)
        return None

    __str__ = __repr__


class frozenset(set):
    def __init__(self, _data=None):
        if JS("(!('__object' in @{{self}}))"):
            set.__init__(self, _data)

    def __hash__(self):
        JS("""
        var hashes = new Array(), obj = @{{self}}.__object, i = 0;
        for (var v in obj) {
            hashes[i++] = v;
        }
        hashes.sort();
        return (@{{self}}.$H = '#frozenset#' + hashes.join("|"));
""")

    def add(self, value):
        raise AttributeError('frozenset is immutable')

    def clear(self):
        raise AttributeError('frozenset is immutable')

    def difference_update(self, other):
        raise AttributeError('frozenset is immutable')

    def discard(self, value):
        raise AttributeError('frozenset is immutable')

    def intersection_update(self, other):
        raise AttributeError('frozenset is immutable')

    def pop(self):
        raise AttributeError('frozenset is immutable')

    def symmetric_difference_update(self, other):
        raise AttributeError('frozenset is immutable')

frozenset.__repr__ = set.__repr__
frozenset.__str__ = set.__str__


class property(object):
    # From: http://users.rcn.com/python/download/Descriptor.htm
    # Extended with setter(), deleter() and fget.__doc_ copy
    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
        if not doc is None or not hasattr(fget, '__doc__') :
            self.__doc__ = doc
        else:
            self.__doc__ = fget.__doc__

    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        if self.fget is None:
            raise AttributeError, "unreadable attribute"
        return self.fget(obj)

    def __set__(self, obj, value):
        if self.fset is None:
            raise AttributeError, "can't set attribute"
        self.fset(obj, value)

    def __delete__(self, obj):
        if self.fdel is None:
            raise AttributeError, "can't delete attribute"
        self.fdel(obj)

    def setter(self, fset):
        self.fset = fset
        return self

    def deleter(self, fdel):
        self.fdel = fdel
        return self


class enumerate(object):

    def __init__(self, iterable):
        self.iter = iter(iterable)
        self.index = 0

    def __iter__(self):
        return self

    def next(self):
        v = self.iter.next()
        if v is StopIter:
            return v
        v = (self.index, v)
        self.index += 1
        return v


# See e.g. http://www.python.org/download/releases/2.2.3/descrintro/#cooperation
class super(object):
    _none = NoneType()

    def __init__(self, type, object_or_type = None):
        self.__thisclass__ = type
        if object_or_type is None:
            self.__self__ = self.__self_class__ = None
        else:
            if JS("!@{{_issubtype}}(@{{object_or_type}}, @{{type}})"):
                debugger()
                JS("@{{_issubtype}}(@{{object_or_type}}, @{{type}})")
                raise TypeError("super(type, obj): obj must be an instance or subtype of type")
            if JS("@{{object_or_type}}['$inst'] === true"):
                self.__self_class__ = object_or_type.__class__
            else:
                self.__self_class__ = object_or_type
            self.__self__ = object_or_type

    def __get__(self, obj, type=None):
        _thisclass = JS("@{{self}}['$dict']['__thisclass__']")
        _self = JS("@{{self}}['$dict']['__self__']")
        if _self is None and obj is not None:
            return super(_thisclass, obj)
        else:
            return self

    JS("""\
    func(m$, null, f$, '__getattribute__', 1, ['self', 'attr'], null, null, null, function($self, $attr) {
        var _thisclass = $self['$dict']['__thisclass__'],
            _self = $self['$dict']['__self__'],
            starttype = $self['$dict']['__self_class__'],
            attr = $attr.valueOf(),
            _stopiter = @{{stopiter}},
            cls, iter, next, x, y;

        if ($self['$inst'] !== true) {
            @{{raise}}($new(@{{TypeError}}, B$str("can't apply this __getattribute__ to type object")));
        }
        if ($attr['__class__'] !== @{{str}} && typeof $attr != 'string') {
            @{{raise}}($new(@{{TypeError}}, B$str("attribute name must be string")));
        }
        x = _self['$dict'][attr];
        if (_self['$inst'] !== true || typeof x == "undefined") {
            iter = @{{fcall}}(this, null, @{{iter}}, null, starttype['__mro__']);
            next = @{{getattr}}(iter, 'next');
            for (;;) {
                @{{stopiter}} = true;
                cls = @{{fcall}}(this, null, next, iter);
                @{{stopiter}} = _stopiter;
                if (cls === @{{StopIter}}) {
                    break;
                }
                if (cls === _thisclass) {
                    break;
                }
            }
            for (;;) {
                @{{stopiter}} = true;
                cls = @{{fcall}}(this, null, next, iter);
                @{{stopiter}} = _stopiter;
                if (cls === @{{StopIter}}) {
                    break;
                }
                x = cls['$dict'][attr];
                if (typeof x != "undefined") {
                    break;
                }
            }
        }
        if (typeof x != "undefined") {
            var none = $self['__class__']['$dict']['_none'];
            y = @{{_getattr}}(x, '__get__');
            if (typeof y != "undefined") {
                return y;
            }
            if (_thisclass['$inst'] === false && _self['__class__'] !== @{{module}} && typeof x != "undefined" && typeof x['$inst'] != "undefined") {
                switch (x['__class__']) {
                    case @{{function}}:
                        var _new_dst$ = function ( ) {
                            var args = Array.prototype.slice.call(arguments);
                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                if (arguments.callee['im_self'] !== null) {
                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                }
                            }
                            var a = @{{_getattr}}(arguments.callee, '__call__');
                            if (typeof a == "undefined") {
                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                            }
                            if (args.length >= 3) {
                                var len = args.length;
                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                            }
                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                        _new_dst$['toString'] = function ( ) {
                            try {
                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                            } catch (e) {
                            }
                            try {
                                return "<" + this.__class__.__name__ + " instance>";
                            } catch (e) {
                            }
                            return "<instance>";
                        };
                        _new_dst$['$inst'] = true;
                        if (typeof @{{instancemethod}} == "undefined") {
                            debugger;
                        }
                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                            _new_dst$['__dict__'] = B$dict();
                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                        }
                        _new_dst$['__class__'] = @{{instancemethod}};
                        _new_dst$['im_class'] = _self['$inst'] === true ? _self['__class__'] : _self;
                        _new_dst$['im_func'] = x;
                        _new_dst$['im_self'] = _self['$inst'] === true ? _self : null;
                        x = _new_dst$;
                        break;
                    case @{{staticmethod}}:
                        x = x['im_func'];
                        break;
                    case @{{classmethod}}:
                        var _new_dst$ = function ( ) {
                            var args = Array.prototype.slice.call(arguments);
                            if (arguments.callee['__class__'] === @{{instancemethod}}) {
                                if (arguments.callee['im_self'] !== null) {
                                    return @{{fcall}}.apply(this, [this, null, arguments.callee['im_func'], null, arguments.callee['im_self']].concat(args));
                                }
                            }
                            var a = @{{_getattr}}(arguments.callee, '__call__');
                            if (typeof a == "undefined") {
                                @{{raise}}($new(@{{TypeError}}, B$str("'" + _typeof(arguments.callee) + "' object is not callable")));
                            }
                            if (args.length >= 3) {
                                var len = args.length;
                                if ((args[len-3] === null || args[len-3]['__class__'] === @{{tuple}}) &&
                                    (args[len-2] === null || args[len-3]['__class__'] === @{{dict}}) &&
                                    (args[len-1] === null || typeof args[len-1]['__class__'] == "undefined")) {
                                    return @{{fcallext}}.apply(this, [this, null, a, arguments.callee].concat(args));
                                }
                            }
                            return @{{fcall}}.apply(this, [this, null, a, arguments.callee].concat(args));
                        }
                        _new_dst$['toString'] = function ( ) {
                            try {
                                return @{{mcall}}(this, null, this, '__str__').valueOf();
                            } catch (e) {
                            }
                            try {
                                return "<" + this.__class__.__name__ + " instance>";
                            } catch (e) {
                            }
                            return "<instance>";
                        };
                        _new_dst$['$inst'] = true;
                        if (typeof @{{instancemethod}} == "undefined") {
                            debugger;
                        }
                        if (typeof @{{instancemethod}}['__slots__'] == "undefined" || @{{instancemethod}}['__slots__'].length > 0) {
                            _new_dst$['__dict__'] = B$dict();
                            _new_dst$['$dict'] = _new_dst$['__dict__']['__object'];
                        }
                        _new_dst$['__class__'] = @{{instancemethod}};
                        _new_dst$['im_class'] = _self['$inst'] === true ? _self['__class__'] : _self;
                        _new_dst$['im_func'] = x['im_func'];
                        _new_dst$['im_self'] = _self['$inst'] === true ? _self['__class__'] : _self;
                        x = _new_dst$;
                        break;
                    case @{{bool}}: // Some known to be non-descriptors
                    case @{{int}}:
                    case @{{long}}:
                    case @{{str}}:
                        break;
                    default:
                        // check for __get__ method in x
                        if (x['$inst'] === true) {
                            var get$ = @{{_getattr}}(x, '__get__');
                            if (typeof get$ != 'undefined') {
                                x = @{{fcall}}(this, null, get$, x, _self, _self['__class__']);
                            }
                        }
                        break;
                }
            }
            return x;
        }
        return @{{raise}}($new(@{{AttributeError}}, B$str(attr)));
});""")

# taken from mochikit: range( [start,] stop[, step] )
def xrange(start, stop = None, step = 1):
    if stop is None:
        stop = start
        start = 0
    if not JS("@{{start}}!== null && @{{start}}.__number__ && (@{{start}}.__number__ != 0x01 || isFinite(@{{start}}))"):
        raise TypeError("xrange() integer start argument expected, got %s" % start.__class__.__name__)
    if not JS("@{{stop}}!== null && @{{stop}}.__number__ && (@{{stop}}.__number__ != 0x01 || isFinite(@{{stop}}))"):
        raise TypeError("xrange() integer end argument expected, got %s" % stop.__class__.__name__)
    if not JS("@{{step}}!== null && @{{step}}.__number__ && (@{{step}}.__number__ != 0x01 || isFinite(@{{step}}))"):
        raise TypeError("xrange() integer step argument expected, got %s" % step.__class__.__name__)
    rval = nval = start
    JS("""
    var nstep = (@{{stop}}-@{{start}})/@{{step}};
    nstep = nstep < 0 ? Math.ceil(nstep) : Math.floor(nstep);
    if ((@{{stop}}-@{{start}}) % @{{step}}) {
        nstep++;
    }
    var _stop = @{{start}}+ nstep * @{{step}};
    if (nstep <= 0) @{{nval}} = _stop;
    var x = {
        'next': function(noStop) {
            if (@{{nval}} == _stop) {
                if (noStop === true) {
                    return;
                }
                throw @{{StopIteration}};
            }
            @{{rval}} = @{{nval}};
            @{{nval}} += @{{step}};
""")
    return INT(rval);
    JS("""
        },
        '$genfunc': function() {
            return this.next(true);
        },
        '__iter__': function() {
            return this;
        },
        '__reversed__': function() {
            return @{{xrange}}(@{{!_stop}}-@{{step}}, @{{start}}-@{{step}}, -@{{step}});
        },
        'toString': function() {
            var s = "xrange(";
            if (@{{start}}!= 0) {
                s += @{{start}}+ ", ";
            }
            s += @{{!_stop}};
            if (@{{step}}!= 1) {
                s += ", " + @{{step}};
            }
            return s + ")";
        },
        '__repr__': function() {
            return "'" + this.toString() + "'";
        }
    };
    @{{!x}}['__str__'] = @{{!x}}.toString;
    return @{{!x}};
    """)

def range(start, stop = None, step = 1):
    if stop is None:
        stop = start
        start = 0
    i = start
    if not JS("@{{start}}!== null && @{{start}}.__number__ && (@{{start}}.__number__ != 0x01 || isFinite(@{{start}}))"):
        raise TypeError("xrange() integer start argument expected, got %s" % start.__class__.__name__)
    if not JS("@{{stop}}!== null && @{{stop}}.__number__ && (@{{stop}}.__number__ != 0x01 || isFinite(@{{stop}}))"):
        raise TypeError("xrange() integer end argument expected, got %s" % stop.__class__.__name__)
    if not JS("@{{step}}!== null && @{{step}}.__number__ && (@{{step}}.__number__ != 0x01 || isFinite(@{{step}}))"):
        raise TypeError("xrange() integer step argument expected, got %s" % step.__class__.__name__)
    items = JS("new Array()")
    JS("""
    var nstep = (@{{stop}}-@{{start}})/@{{step}};
    nstep = nstep < 0 ? Math.ceil(nstep) : Math.floor(nstep);
    if ((@{{stop}}-@{{start}}) % @{{step}}) {
        nstep++;
    }
    var _stop = @{{start}}+ nstep * @{{step}};
    if (nstep <= 0) @{{i}}= _stop;
    for (; @{{i}}!= _stop; @{{i}}+= @{{step}}) {
""")
    items.push(int(i))
    JS('}')
    return list(items)
xrange = range

def ord(x):
    JS("""
    if (typeof @{{x}} == "string") {
        if (@{{x}}.length == 1) {
            return $new(@{{int}}, @{{x}}.charCodeAt(0));
        }
    } else if (@{{x}}['$inst'] === true) {
        var s = @{{x}}['__s'];
        if (typeof s == "string") {
            if (s.length == 1) {
                return $new(@{{int}}, s.charCodeAt(0));
            }
        }
    }
    return @{{raise}}($new(@{{TypeError}}, B$str("ord() expected string of length 1")));
""")

def chr(x):
    JS("""
    return B$str(String.fromCharCode(@{{x}}.valueOf()));
    """)

def is_basetype(x):
    JS("""
       var t = typeof(@{{x}});
       return t == 'boolean' ||
       t == 'function' ||
       t == 'number' ||
       t == 'string' ||
       t == "undefined";
    """)

def get_pyjs_classtype(x):
    JS("""
        if (@{{x}}!== null && typeof @{{x}}.__is_instance__ == 'boolean') {
            var src = @{{x}}.__name__;
            return src;
        }
        return null;
    """)

_str_None = "None"
_str_True = "True"
_str_False = "False"
_str_zero = "0"
_str_one = "1"
_str_minus_one = "-1"
_str_undefined = "undefined"


JS("""
func(m$, null, g$, 'repr', 1, ['object'], null, null, null, function($object) {
    switch ($object) {
        case null:
        case @{{None}}:
            return @{{_str_None}};
        case true:
        case @{{True}}:
            return @{{_str_True}};
        case false:
        case @{{False}}:
            return @{{_str_False}};
        case 0:
        case @{{int_zero}}:
            return @{{_str_zero}};
        case 1:
        case @{{int_one}}:
            return @{{_str_one}};
        case -1:
        case @{{int_zero}}:
            return @{{_str_minus_one}};
        default:
            var t = typeof($object);
            switch (t) {
                case "undefined":
                    return @{{_str_undefined}};
                case "string":
                    return B$str("'" + $object.replace("'", "\\'") + "'")
                case "number":
                    return B$str($object.toString())
            }
            switch ($object['__class__']) {
                case @{{str}}:
                    return B$str("'" + $object.__s.replace("'", "\\'") + "'")
                case @{{int}}:
                    return B$str($object.__v.toString());
            }
            var r = @{{_getattr}}($object, '__repr__');
            if (typeof r != "undefined") {
                return @{{fcall}}(this, null, r, $object);
            }
            switch (t) {
                case "function":
                    return B$str("<function '" + $object.name + "'>");
                case "object":
                    return B$str($object.toString());
            }
    }
    return B$str($object.toString());
});

func(m$, null, g$, 'len', 1, ['object'], null, null, null, function($object) {
    if (typeof $object == "undefined") {
       @{{raise}}($new(@{{UndefinedValueError}}, B$str("len: object")));
    }
    if ($object === null)
        return @{{int_zero}};
    if (typeof $object.__array != "undefined")
        return $new(@{{int}}, $object.__array.length);
    if ($object.__class__ == @{{str}})
        return $new(@{{int}}, $object.__s.length);
    if (typeof $object._length != "undefined")
        return $new(@{{int}}, $object._length);
    if (typeof $object != 'function') {
        if (typeof $object.length != "undefined")
            return $new(@{{int}}, $object.length);
    }
    var v = @{{getattr}}($object, '__len__', N$);
    if (v !== N$)
       return @{{fcall}}(this, null, v, null);
    @{{raise}}($new(@{{TypeError}}, B$str("object has no len()")));
});

func(m$, null, g$, 'isinstance', 1, ['object', 'classinfo'], null, null, null, function($object, $classinfo) {
    var mro, cls, classes = $classinfo['__class__'] === @{{tuple}} ? $classinfo['__array'] : $classinfo;
    if (typeof $object['$inst'] == "undefined") {
        return @{{False}};
    }
    if (!(classes instanceof Array)) {
        classes = [classes];
    }
    if (typeof $object != "undefined" && $object !== null) {
        cls = $object['__class__'];
        for (var i = 0; i < classes.length; i++) {
            if (classes[i]['$inst'] !== false) {
                if (classes[i]['__class__'] !== @{{tuple}}) {
                    @{{raise}}($new(@{{TypeError}}, B$str("isinstance() arg 2 must be a class, type, or tuple of classes and types")));
                }
                if (@{{isinstance}}($object, classes[i]) === @{{True}}) {
                    return @{{True}};
                }
            }
            mro = cls.__mro__;
            for (var j = 0; j < mro.length; j++) {
                if (mro[j] === classes[i]) {
                    return @{{True}};
                }
            }
        }
    }
    return @{{False}};
});

func(m$, null, g$, 'issubclass', 1, ['class', 'classinfo'], null, null, null, function($class, $classinfo) {
    if (typeof $class == "undefined" || $class === null || $class['$inst'] !== false) {
        @{{raise}}($new(@{{TypeError}}, B$str("arg 1 must be a class")));
    }
    var mro, classes = $classinfo['__class__'] === @{{tuple}} ? $classinfo['__array'] : [$classinfo];
    mro = $class['__mro__'];
    for (var i = 0; i < classes.length; i++) {
        if (classes[i]['$inst'] !== false) {
            @{{raise}}($new(@{{TypeError}}, B$str("issubclass() arg 2 must be a class or tuple of classes")));
        }
        for (var j = 0; j < mro.length; j++) {
            if (mro[j] === classes[i]) {
                return @{{True}};
            }
        }
    }
    return @{{False}};
});

func(m$, null, g$, '_issubclass', 1, ['class', 'classinfo'], null, null, null, function($class, $classinfo) {
    if (typeof $class == "undefined" || $class === null || $class['$inst'] !== false) {
        return false;
    }
    var mro, classes = $classinfo['__class__'] === @{{tuple}} ? $classinfo['__array'] : $classinfo instanceof Array ? $classinfo : [$classinfo];
    mro = $class['__mro__'];
    for (var i = 0; i < classes.length; i++) {
        if (classes[i]['$inst'] !== false) {
            return false;
        }
        for (var j = 0; j < mro.length; j++) {
            if (mro[j] === classes[i]) {
                return true;
            }
        }
    }
    return false;
});

func(m$, null, g$, '_issubtype', 1, ['obj', 'type'], null, null, null, function($obj, $type) {
    if (typeof $obj == "undefined" || $obj === null || typeof $obj['$inst'] != 'boolean') {
        return false;
    }
    if (typeof $type == "undefined" || $type === null || typeof $type['$inst'] != 'boolean') {
        return false;
    }
    var mro = $obj['$inst'] === true ? $obj['__class__']['__mro__'] : $obj['__mro__'];
    for (var j = 0; j < mro.length; j++) {
        if (mro[j] === $type) {
            return true;
        }
    }
    return false;
});

func(m$, null, g$, 'callable', 1, ['obj'], null, null, null, function($obj) {
    if (typeof $obj == 'function') {
        if ($obj['$inst'] !== true ||
            $obj['__class__'] === @{{function}} ||
            $obj['__class__'] === @{{instancemethod}}) {
            return @{{True}};
        }
        // Only check the $dict from the classes
        // and skip the class.__call__
        var mro = $obj['__class__']['__mro__'],
            f;
        for (var i = 0; i < mro.length; i++) {
            f = mro[i]['$dict']['__call__'];
            if (typeof f != "undefined") {
                break;
            }
        }
        if (typeof f == 'function') return @{{True}};
    }
    return @{{False}};
});

func(m$, null, g$, 'dir', 1, ['obj'], null, null, null, function($obj) {
    if (typeof $obj == "undefined") {
        @{{raise}}($new(@{{UndefinedValueError}}, B$str("dir(obj)")));
    }
    var $dict, props = {},
        mro = $obj['$inst'] === true ? $obj['__class__']['__mro__'] : $obj['__mro__'];
    for (var i = mro.length - 1; i >= 0; i--) {
        $dict = mro[i]['$dict'];
        for (var a in $dict) {
            if (a.charAt(0) != '#') {
                props[a] = $dict[a];
            }
        }
    }
    if ($obj['$inst'] === true) {
        $dict = $obj['$dict'];
        for (var a in $dict) {
            if (a.charAt(0) != '#') {
                props[a] = $dict[a];
            }
        }
    }
    var properties = B$tuple();
    var __array = properties.__array;
    for (var a in props) {
        __array.push(B$str(a));
    }
    return properties;
});
""")

def filter(obj, method, sequence=None):
    # object context is LOST when a method is passed, hence object must be passed separately
    # to emulate python behaviour, should generate this code inline rather than as a function call
    items = []
    if sequence is None:
        sequence = method
        method = obj

        for item in sequence:
            if method(item):
                items.append(item)
    else:
        for item in sequence:
            if method.call(obj, item):
                items.append(item)

    return items


def map(obj, method, sequence=None):
    items = []

    if sequence is None:
        sequence = method
        method = obj

        for item in sequence:
            items.append(method(item))
    else:
        for item in sequence:
            items.append(method.call(obj, item))

    return items


def reduce(func, iterable, initializer=JS("null")):
    try:
        iterable = iter(iterable)
    except:
        raise TypeError, "reduce() arg 2 must support iteration"
    empty = True
    for value in iterable:
        empty = False
        if JS("""@{{initializer}} === null || typeof @{{initializer}} == "undefined" """):
            initializer = value
        else:
            initializer = func(initializer, value)
    if empty:
        if JS("""@{{initializer}} === null || typeof @{{initializer}} == "undefined" """):
            raise TypeError, "reduce() of empty sequence with no initial value"
        return initializer
    return initializer


def zip(*iterables):
    n = len(iterables)
    if n == 0:
        return []
    lst = []
    iterables = [iter(i) for i in iterables]
    try:
        while True:
            t = []
            i = 0
            while i < n:
                t.append(iterables[i].next())
                i += 1
            lst.append(tuple(t))
    except StopIteration:
        pass
    return lst


def sorted(iterable, cmp=None, key=None, reverse=False):
    lst = list(iterable)
    lst.sort(cmp, key, reverse)
    return lst


def reversed(iterable):
    if hasattr(iterable, '__reversed__'):
        return iterable.__reversed__()
    if hasattr(iterable, '__len__') and hasattr(iterable, '__getitem__'):
        if len(iterable) == 0:
            l = []
            return l.__iter__()
        try:
            v = iterable[0]
            return _reversed(iterable)
        except:
            pass
    raise TypeError("argument to reversed() must be a sequence")

def _reversed(iterable):
    rev = []
    for i in iterable:
        rev.insert(0, i)
    return rev
    #i = len(iterable)
    #while i > 0:
    #    i -= 1
    #    yield iterable[i]


def iter(iterable, sentinel=None):
    if sentinel is None:
        i = getattr(iterable, '__iter__', None)
        if i is not None:
            return i()
        i = getattr(iterable, '__getitem__', None)
        if i is not None:
            return _iter_getitem(iterable)
        if JS("@{{iterable}} instanceof Array"):
            return list(iterable).__iter__()
        raise TypeError("object is not iterable")
    if callable(iterable):
        return _iter_callable(iterable, sentinel)
    raise TypeError("iter(v, w): v must be callable")

def _iter_getitem(object):
    debugger() # not tested
    items = []
    i = -1
    try:
        i += 1
        items.append(object[i])
    except IndexError:
        pass
    return items
    #i = 0
    #try:
    #    while True:
    #        yield object[i]
    #        i += 1
    #except IndexError:
    #    pass

def _iter_callable(callable, sentinel):
    while True:
        nextval = callable()
        if nextval == sentinel:
            break
        #yield nextval

def min(*sequence):
    if len(sequence) == 1:
        sequence = sequence[0]
    minValue = None
    for item in sequence:
        if minValue is None:
            minValue = item
        elif cmp(item, minValue) == -1:
            minValue = item
    return minValue


def max(*sequence):
    if len(sequence) == 1:
        sequence = sequence[0]
    maxValue = None
    for item in sequence:
        if maxValue is None:
            maxValue = item
        elif cmp(item, maxValue) == 1:
            maxValue = item
    return maxValue

def sum(iterable, start=None):
    if start is None:
        start = 0
    for i in iterable:
        start += i
    return start


# type functions from Douglas Crockford's Remedial Javascript: http://www.crockford.com/javascript/remedial.html
def isObject(a):
    JS("""
    return (@{{a}}!== null && (typeof @{{a}}== 'object')) || typeof @{{a}}== 'function';
    """)

def isFunction(a):
    JS("""
    return typeof @{{a}}== 'function';
    """)

def isString(a):
    JS("""
    return typeof @{{a}}== 'string';
    """)

def isNull(a):
    JS("""
    return typeof @{{a}}== 'object' && !@{{a}};
    """)

def isArray(a):
    JS("""
    return @{{isObject}}(@{{a}}) && @{{a}}.constructor === Array;
    """)

def isUndefined(a):
    JS("""
    return typeof @{{a}}== "undefined";
    """)

def isIteratable(a):
    return hasattr(a, '__iter__')

def isNumber(a):
    JS("""
    return @{{a}}!== null && @{{a}}.__number__ &&
           (@{{a}}.__number__ != 0x01 || isFinite(@{{a}}));
    """)

def isInteger(a):
    JS("""
    switch (@{{a}}.__number__) {
        case 0x01:
            if (@{{a}} != Math.floor(@{{a}})) break;
        case 0x02:
        case 0x04:
            return true;
    }
    return false;
""")

def isSet(a):
    JS("""
    if (@{{a}}=== null) return false;
    if (typeof @{{a}}.__object == "undefined") return false;
    var a_mro = @{{a}}['__class__']['__mro__'];
    switch (a_mro[a_mro.length-2]) {
        case @{{set}}:
            return 1;
        case @{{frozenset}}:
            return 2;
    }
    return false;
""")
def toJSObjects(x):
    """
       Convert the pyjs pythonic list and dict objects into javascript Object and Array
       objects, recursively.
    """
    if isArray(x):
        JS("""
        var result = [];
        for(var k=0; k < @{{x}}.length; k++) {
           var v = @{{x}}[k];
           var tv = @{{toJSObjects}}(v);
           result.push(tv);
        }
        return result;
        """)
    if isObject(x):
        if x.__number__:
            return x.valueOf()
        elif isinstance(x, dict):
            JS("""
            var o = @{{x}}.getObject();
            var result = {};
            for (var i in o) {
               result[o[i][0].toString()] = @{{toJSObjects}}(o[i][1]);
            }
            return result;
            """)
        elif isinstance(x, list):
            return toJSObjects(x.__array)
        elif hasattr(x, '__class__'):
            # we do not have a special implementation for custom
            # classes, just pass it on
            return x
    if isObject(x):
        JS("""
        var result = {};
        for(var k in @{{x}}) {
            var v = @{{x}}[k];
            var tv = @{{toJSObjects}}(v);
            result[k] = tv;
            }
            return result;
         """)
    if isString(x):
        return str(x)
    return x

def sprintf(strng, args):
    # See http://docs.python.org/library/stdtypes.html
    JS(r"""
    var re_dict = /([^%]*)%[(]([^)]+)[)]([#0\x20\x2B-]*)(\d+)?(\.\d+)?[hlL]?(.)((.|\n)*)/;
    var re_list = /([^%]*)%([#0\x20\x2B-]*)(\*|(\d+))?(\.\d+)?[hlL]?(.)((.|\n)*)/;
    var re_exp = /(.*)([+-])(.*)/;

    var argidx = 0;
    var nargs = 0;
    var result = [];
    var strng = @{{strng}}.valueOf();
    var remainder = strng;

    function formatarg(flags, minlen, precision, conversion, param) {
        var subst = '';
        var numeric = true;
        var left_padding = 1;
        var padchar = ' ';
        if (minlen === null || minlen == 0 || !minlen) {
            minlen=0;
        } else {
            minlen = parseInt(minlen);
        }
        if (!precision) {
            precision = null;
        } else {
            precision = parseInt(precision.substr(1));
        }
        if (flags.indexOf('-') >= 0) {
            left_padding = 0;
        }
        switch (conversion) {
            case '%':
                numeric = false;
                subst = '%';
                break;
            case 'c':
                numeric = false;
                subst = String.fromCharCode(parseInt(param.toString()));
                break;
            case 'd':
            case 'i':
            case 'u':
                subst = '' + parseInt(param.toString());
                break;
            case 'e':
                if (precision === null) {
                    precision = 6;
                }
                subst = re_exp.exec(String(param.valueOf().toExponential(precision)));
                if (subst[3].length == 1) {
                    subst = subst[1] + subst[2] + '0' + subst[3];
                } else {
                    subst = subst[1] + subst[2] + subst[3];
                }
                break;
            case 'E':
                if (precision === null) {
                    precision = 6;
                }
                subst = re_exp.exec(String(param.valueOf().toExponential(precision)).toUpperCase());
                if (subst[3].length == 1) {
                    subst = subst[1] + subst[2] + '0' + subst[3];
                } else {
                    subst = subst[1] + subst[2] + subst[3];
                }
                break;
            case 'f':
                if (precision === null) {
                    precision = 6;
                }
                subst = String(parseFloat(param.toString()).toFixed(precision));
                break;
            case 'F':
                if (precision === null) {
                    precision = 6;
                }
                subst = String(parseFloat(param.toString()).toFixed(precision)).toUpperCase();
                break;
            case 'g':
                if (precision === null && flags.indexOf('#') >= 0) {
                    precision = 6;
                }
                var p = param.valueOf();
                if (p >= 1E6 || p < 1E-5) {
                    subst = String(precision === null ? p.toExponential() : p.toExponential().toPrecision(precision));
                } else {
                    subst = String(precision === null ? parseFloat(p) : parseFloat(p).toPrecision(precision));
                }
                break;
            case 'G':
                if (precision === null && flags.indexOf('#') >= 0) {
                    precision = 6;
                }
                var p = param.valueOf();
                if (p >= 1E6 || p < 1E-5) {
                    subst = String(precision === null ? p.toExponential() : p.toExponential().toPrecision(precision)).toUpperCase();
                } else {
                    subst = String(precision === null ? parseFloat(p) : parseFloat(p).toPrecision(precision)).toUpperCase().toUpperCase();
                }
                break;
            case 'r':
                numeric = false;
                subst = @{{repr}}(param).__s;
                break;
            case 's':
                numeric = false;
                subst = $new(@{{str}}, param).__s;
                break;
            case 'o':
                subst = param.valueOf().toString(8);
                if (subst != '0' && flags.indexOf('#') >= 0) {
                    subst = '0' + subst;
                }
                break;
            case 'x':
                subst = param.valueOf().toString(16);
                if (flags.indexOf('#') >= 0) {
                    if (left_padding) {
                        subst = @{{str}}['$dict']['rjust'](subst, minlen - 2, '0').__s;
                    }
                    subst = '0x' + subst;
                }
                break;
            case 'X':
                subst = param.valueOf().toString(16).toUpperCase();
                if (flags.indexOf('#') >= 0) {
                    if (left_padding) {
                        subst = @{{str}}['$dict']['rjust'](subst, minlen - 2, '0').__s;
                    }
                    subst = '0x' + subst;
                }
                break;
            default:
                @{{raise}}($new(@{{ValueError}}, B$str("unsupported format character '" + conversion + "' ("+@{{hex}}(conversion.charCodeAt(0))+") at index " + (@{{strng}}.valueOf().length - remainder.length - 1))));
        }
        if (minlen && subst.length < minlen) {
            if (numeric && left_padding && flags.indexOf('0') >= 0) {
                padchar = '0';
            }
            subst = @{{str}}['$dict'][left_padding ? 'rjust' : 'ljust'](subst, minlen, padchar).__s;
        }
        return subst;
    }

    function sprintf_list(strng, args) {
        var a, left, flags, precision, conversion, minlen, param,
            __array = result;
        while (remainder) {
            a = re_list.exec(remainder);
            if (a === null) {
                __array[__array.length] = remainder;
                break;
            }
            left = a[1]; flags = a[2];
            minlen = a[3]; precision = a[5]; conversion = a[6];
            remainder = a[7];
            if (typeof minlen == "undefined") minlen = null;
            if (typeof precision == "undefined") precision = null;
            if (typeof conversion == "undefined") conversion = null;
            __array[__array.length] = left;
            if (minlen == '*') {
                if (argidx == nargs) {
                    @{{raise}}($new(@{{TypeError}}, B$str("not enough arguments for format string")));
                }
                minlen = args['__class__']['$dict']['__getitem__'](args, argidx++);
                switch (minlen.__number__) {
                    case 0x02:
                    case 0x04:
                        break;
                    case 0x01:
                        if (minlen == Math.floor(minlen)) {
                            break;
                        }
                    default:
                        @{{raise}}($new(@{{TypeError}}, B$str("* wants int")));
                }
            }
            if (conversion != '%') {
                if (argidx == nargs) {
                    @{{raise}}($new(@{{TypeError}}, B$str("not enough arguments for format string")));
                }
                param = args['__class__']['$dict']['__getitem__'](args, argidx++);
            }
            __array[__array.length] = formatarg(flags, minlen, precision, conversion, param);
        }
    }

    function sprintf_dict(strng, args) {
        var a = null,
            left = null,
            flags = null,
            precision = null,
            conversion = null,
            minlen = null,
            minlen_type = null,
            key = null,
            arg = args,
            param,
            __array = result;

        argidx++;
        while (remainder) {
            a = re_dict.exec(remainder);
            if (a === null) {
                __array[__array.length] = remainder;
                break;
            }
            left = a[1]; key = a[2]; flags = a[3];
            minlen = a[4]; precision = a[5]; conversion = a[6];
            remainder = a[7];
            if (typeof minlen == "undefined") minlen = null;
            if (typeof precision == "undefined") precision = null;
            if (typeof conversion == "undefined") conversion = null;
            __array[__array.length] = left;
            param = arg['__class__']['$dict']['__getitem__'](arg, key);
            __array[__array.length] = formatarg(flags, minlen, precision, conversion, param);
        }
    }

    if (strng.indexOf("%(") >= 0) {
        if (re_dict.exec(strng) !== null) {
            if (@{{args}}['__class__'] !== @{{dict}}) {
                @{{raise}}($new(@{{TypeError}}, B$str("format requires a mapping")));
            }
            sprintf_dict(strng, @{{args}});
            return B$str(result.join(""));
        }
    }
    if (@{{args}}['__class__'] !== @{{tuple}}) {
        if (@{{args}} instanceof Array) {
            @{{args}} = B$tuple(@{{args}});
        } else {
            @{{args}} = B$tuple([@{{args}}]);
        }
    }
    nargs = @{{args}}.__array.length;
    sprintf_list(strng, @{{args}});
    if (argidx != nargs) {
        @{{raise}}($new(@{{TypeError}}, B$str("not all arguments converted during string formatting")));
    }
    return B$str(result.join(""));
""")

def debugReport(msg):
    JS("""
    alert(@{{msg}}.valueOf());
    """)

JS("""
var $printFunc = null;
if (   typeof $wnd.console != "undefined"
    && typeof $wnd.console.debug == 'function') {
    $printFunc = function(s) {
        $wnd.console.debug(s);
    };
} else if (   typeof $wnd.opera != "undefined"
           && typeof $wnd.opera.postError == 'function') {
    $printFunc = function(s) {
        $wnd.opera.postError(s);
    };
} else if ( typeof console != "undefined") {
    if (   typeof console.log == 'function'
        || typeof console.log == 'object') {
        $printFunc = function(s) {
            console.log(s);
        };
    }
}
""")

def _print_to_console(s):
    JS("""
    if ($printFunc === null) return null;
    $printFunc(@{{s}}.valueOf());
    """)

def printFunc(objs, newline):
    # objs is an javascript array
    # newline is javascript true/false
    s = ' '.join([str(i) for i in list(objs)])
    if newline:
        s += '\n'
    sys.stdout.write(s);

def pow(x, y, z = None):
    p = None
    JS("@{{p}} = Math.pow(@{{x}}, @{{y}});")
    if z is None:
        return float(p)
    return float(p % z)

def hex(x):
    JS("""
    if (typeof @{{x}} == 'number') {
        if (Math.floor(@{{x}}) == @{{x}}) {
            return B$str('0x' + @{{x}}.toString(16));
        }
    } else {
        switch (@{{x}}.__number__) {
            case 0x02:
                return B$str('0x' + @{{x}}.__v.toString(16));
            case 0x04:
                return @{{long}}['$dict']['__hex__'](@{{x}});
        }
    }
""")
    raise TypeError("hex() argument can't be converted to hex")

def oct(x):
    JS("""
    if (typeof @{{x}} == 'number') {
        if (Math.floor(@{{x}}) == @{{x}}) {
            return B$str(@{{x}} == 0 ? '0': '0' + @{{x}}.toString(8));
        }
    } else {
        switch (@{{x}}.__number__) {
            case 0x02:
                return B$str(@{{x}}.__v == 0 ? '0': '0' + @{{x}}.__v.toString(8));
            case 0x04:
                return @{{long}}['$dict']['__oct__'](@{{x}});
        }
    }
""")
    raise TypeError("oct() argument can't be converted to oct")

def round(x, n = 0):
    n = pow(10, n)
    r = None
    JS("@{{r}} = Math.round(@{{n}}*@{{x}})/@{{n}};")
    return float(r)

def divmod(x, y):
    JS("""
    if (@{{x}} !== null && @{{y}} !== null) {
        switch ((@{{x}}.__number__ << 8) | @{{y}}.__number__) {
            case 0x0101:
            case 0x0104:
            case 0x0401:
                if (@{{y}} == 0) @{{raise}}($new(@{{ZeroDivisionError}}, B$str("float divmod()")));
                var f = Math.floor(@{{x}} / @{{y}});
                return @{{tuple}}([f, @{{x}} - f * @{{y}}]);
            case 0x0102:
                if (@{{y}}.__v == 0) @{{raise}}($new(@{{ZeroDivisionError}}, B$str("float divmod()")));
                var f = Math.floor(@{{x}} / @{{y}}.__v);
                return @{{tuple}}([f, @{{x}} - f * @{{y}}.__v]);
            case 0x0201:
                if (@{{y}} == 0) @{{raise}}($new(@{{ZeroDivisionError}}, B$str("float divmod()")));
                var f = Math.floor(@{{x}}.__v / @{{y}});
                return @{{tuple}}([f, @{{x}}.__v - f * @{{y}}]);
            case 0x0202:
                if (@{{y}}.__v == 0) @{{raise}}($new(@{{ZeroDivisionError}}, B$str("integer division or modulo by zero")));
                var f = Math.floor(@{{x}}.__v / @{{y}}.__v);
                return @{{tuple}}([new @{{int}}(f), new @{{int}}(@{{x}}.__v - f * @{{y}}.__v)]);
            case 0x0204:
                return @{{long}}['$dict']['__rdivmod__'](@{{y}}, @{{long}}(@{{x}}.__v));
            case 0x0402:
                return @{{long}}['$dict']['__divmod__'](@{{x}}, @{{long}}(@{{y}}.__v));
            case 0x0404:
                return @{{long}}['$dict']['__divmod__'](@{{x}}, @{{y}});
        }
        if (!@{{x}}.__number__) {
            if (   !@{{y}}.__number__
                && @{{x}}.__mro__.length > @{{y}}.__mro__.length
                && @{{isinstance}}(@{{x}}, @{{y}})
                && typeof @{{x}}['__divmod__'] == 'function')
                return @{{y}}.__divmod__(@{{x}});
            if (typeof @{{x}}['__divmod__'] == 'function') return @{{x}}.__divmod__(@{{y}});
        }
        if (!@{{y}}.__number__ && typeof @{{y}}['__rdivmod__'] == 'function') return @{{y}}.__rdivmod__(@{{x}});
    }
""")
    raise TypeError("unsupported operand type(s) for divmod(): '%r', '%r'" % (x, y))

def all(iterable):
    for element in iterable:
        if not element:
            return False
    return True

def any(iterable):
    for element in iterable:
        if element:
            return True
    return False

__iter_prepare = JS("""function(iter, reuse_tuple) {

    if (typeof iter == "undefined") {
        @{{raise}}($new(@{{TypeError}}, B$str("iter is undefined")));
    }
    var it = {};
    it.$iter = iter;
    it.$loopvar = 0;
    it.$reuse_tuple = reuse_tuple;
    if (typeof (it.$arr = iter.__array) != "undefined") {
        it.$gentype = 0;
    } else {
        it.$iter = iter.__iter__();
        it.$gentype = typeof (it.$arr = iter.__array) != "undefined"? 0 : (typeof iter.$genfunc == 'function'? 1 : -1);
    }
    return it;
}""")

__wrapped_next = JS("""function(it) {
    var iterator = it.$iter;
    it.$nextval = it.$gentype?(it.$gentype > 0?
        iterator.next(true,it.$reuse_tuple):@{{wrapped_next}}(iterator)
                              ) : it.$arr[it.$loopvar++];
    return it;
}""")

# For optimized for loops: fall back for userdef iterators
wrapped_next = JS("""function (iter) {
    try {
        var res = iter.next();
    } catch (e) {
        if (e === @{{StopIteration}}) {
            return;
        }
        throw e;
    }
    return res;
}""")

_handle_exception = JS("""function(err) {
    $pyjs.loaded_modules['sys'].save_exception_stack();

    if (!$pyjs.in_try_except) {
        var $pyjs_msg = $pyjs.loaded_modules['sys']._get_traceback(err);
        $pyjs.__active_exception_stack__ = null;
        @{{printFunc}}([$pyjs_msg], true);
        @{{debugReport}}($pyjs_msg);
    }
    throw err;
};
""")
init()

a = {'a': 1}
for b in a.iteritems():
    pass

class Foo(object):
    a = 0
    def fn(self):
        return 'fn'
f = Foo()
s = str(f.fn)
max_i = 1#000000#
if max_i > 10:
    JS("alert('start')")
    t1 = JS("new Date()")
i = 0
while i < max_i:
    i = i + 1
    f = Foo()
    f.a = i
if max_i > 10:
    t2 = JS("new Date()")
    JS("alert('end ' + (@{{t2}}.getTime() - @{{t1}}.getTime()) / 1000.0)")
for i in [1]:
    a = 1

# Taken from importlib and slighly adapted:
# - _cgd_import
# - __import__

def _gcd_import(name, package=None, level=0):
    if package:
        if not hasattr(package, 'rindex'):
            raise ValueError("__package__ not set to a string")
        elif package not in sys.modules:
            msg = "Parent module '%s' not loaded, cannot perform relative import"
            raise SystemError(msg % package)
    if not name and level == 0:
        raise ValueError("Empty module name")
    if level > 0:
        dot = len(package)
        for x in range(level, 1, -1):
            try:
                dot = package.rindex('.', 0, dot)
            except ValueError:
                raise ValueError("attempted relative import beyond top-level package")
        if name:
            name = "%s.%s" % (package[:dot], name)
        else:
            name = package[:dot]
    if name in sys.modules:
        module = sys.modules[name]
        if module is None:
            message = "import of %s halted; None in sys.modules" % name
            raise ImportError(message)
        return module
    parent = name.rpartition('.')[0]
    path = None
    if parent:
        if parent not in sys.modules:
            _gcd_import(parent)
        # Backwards-compatibility; be nicer to skip the dict lookup.
        parent_module = sys.modules[parent]
        try:
            path = parent_module.__path__
        except AttributeError:
            msg = "No module named '%s'; %s is not a package" % (name, parent)
            #raise ImportError(msg)
    finder = imp.find_module(name, path)
    if finder is not None:
        module = imp.load_module(name, *finder)
    else:
        raise ImportError("No module named '%s'" % name)
    if parent:
        # Set the module as an attribute on its parent.
        setattr(parent_module, name.rpartition('.')[2], module)
    # Set __package__ if the loader did not.
    if not hasattr(module, '__package__') or module.__package__ is None:
        # Watch out for what comes out of sys.modules to not be a module,
        # e.g. an int.
        try:
            module.__package__ = module.__name__
            if not hasattr(module, '__path__'):
                module.__package__ = module.__package__.rpartition('.')[0]
        except AttributeError:
            pass
    return module

def __import__(name, globals={}, locals={}, fromlist=[], level=0):
    """Import a module.

    The 'globals' argument is used to infer where the import is occuring from
    to handle relative imports. The 'locals' argument is ignored. The
    'fromlist' argument specifies what should exist as attributes on the module
    being imported (e.g. ``from module import <fromlist>``).  The 'level'
    argument represents the package location to import from in a relative
    import (e.g. ``from ..pkg import mod`` would have a 'level' of 2).

    """
    if not hasattr(name, 'rpartition'):
        raise TypeError("module name must be str, not %s" %type(name))
    if level == 0:
        module = _gcd_import(name)
    else:
        # __package__ is not guaranteed to be defined or could be set to None
        # to represent that its proper value is unknown
        package = globals.get('__package__')
        if package is None:
            package = globals['__name__']
            if '__path__' not in globals:
                package = package.rpartition('.')[0]
        if level > 0:
            module = _gcd_import(name, package, level)
        else:
            try:
                module = _gcd_import(name, package, 1)
            except ImportError:
                module = _gcd_import(name, package, 0)
    # The hell that is fromlist ...
    if not fromlist:
        # Return up to the first dot in 'name'. This is complicated by the fact
        # that 'name' may be relative.
        if level == 0:
            return sys.modules[name.partition('.')[0]]
        elif not name:
            return module
        else:
            cut_off = len(name) - len(name.partition('.')[0])
            if cut_off == 0:
                return sys.modules[module.__name__]
            return sys.modules[module.__name__[:-cut_off]]
    else:
        # If a package was imported, try to import stuff from fromlist.
        if '*' in fromlist and hasattr(module, '__all__'):
            fromlist[:] = list(fromlist)
            fromlist.remove('*')
            fromlist.extend(module.__all__)
        none = NoneType()
        for x in fromlist:
            # In cPython we would do
            # if not hasattr(module, x):
            # we've got the globals and builtins mixed up
            y1 = getattr(module, x, none)
            y2 = getattr(__builtins__, x, none)
            if y1 is none or (module is not __builtins__ and y1 is y2):
                try:
                    subname = '%s.%s' % (module.__name__, x)
                    _gcd_import(subname)
                    #_gcd_import('%s.%s' % (module.__name__, x))
                except ImportError:
                    pass
    return module

# The import function is used in the translated code
def _import(assnames, name, globals, locals, fromlist, level):
    name = JS("typeof @{{name}} == 'string' ? $new(@{{str}}, @{{name}}) : @{{name}}")
    _globals = JS("B$dict(@{{globals}})")
    _fromlist = JS("B$list(@{{fromlist}})")
    _level = JS("@{{level}} === null ? @{{int_minus_one}} : $new(@{{int}}, @{{level}});")
    star = '*'
    module = None
    module = __import__(name, _globals, None, _fromlist, _level)
    JS("""
    var name, v, src, dst;
    for (var i = 0; i < @{{assnames}}.length; i++) {
        src = @{{assnames}}[i][0];
        dst = @{{assnames}}[i][1];
        name = src.valueOf()
        if (name.valueOf() != '*') {
            v = @{{module}}['$dict'][name];
            if (typeof v == "undefined") {
                @{{raise}}($new(@{{ImportError}}, B$str("cannot import name " + name)));
            }
            @{{locals}}[dst === null ? name : dst.valueOf()] = v;
        } else if (@{{list}}['$dict']['count'](@{{_fromlist}}, @{{star}}).valueOf() > 0) {
            for (name in @{{module}}['$dict']) {
                if (name.charAt(0) != '_') {
                    v = @{{module}}['$dict'][name];
                    if (typeof v != "undefined") {
                        @{{locals}}[name] = v;
                    }
                }
            }
        } else {
            for (var i = 0; i < @{{_fromlist}}.__array.length; i++) {
                name = @{{_fromlist}}.__array[i]['__s'];
                v = @{{module}}['$dict'][name]
                if (typeof v == "undefined") {
                    @{{raise}}($new(@{{ImportError}}, B$str("cannot import name " + name)));
                }
                @{{locals}}[name] = v;
            }
        }
    }
    """)
    return module

def _start_main(name):
    name = JS("typeof @{{name}} == 'string' ? $new(@{{str}}, @{{name}}) : @{{name}}")
    imp.load_module('__main__', *imp.find_module(name))



__all__ = []
for name in [
    'ArithmeticError',
    'AssertionError',
    'AttributeError',
    'BaseException',
    'BufferError',
    'BytesWarning',
    'DeprecationWarning',
    'EOFError',
    'Ellipsis',
    'EnvironmentError',
    'Exception',
    'False',
    'FloatingPointError',
    'FutureWarning',
    'GeneratorExit',
    'IOError',
    'ImportError',
    'ImportWarning',
    'IndentationError',
    'IndexError',
    'KeyError',
    'KeyboardInterrupt',
    'LookupError',
    'MemoryError',
    'NameError',
    'None',
    'NotImplemented',
    'NotImplementedError',
    'OSError',
    'OverflowError',
    'PendingDeprecationWarning',
    'ReferenceError',
    'RuntimeError',
    'RuntimeWarning',
    'StandardError',
    'StopIteration',
    'SyntaxError',
    'SyntaxWarning',
    'SystemError',
    'SystemExit',
    'TabError',
    'True',
    'TypeError',
    'UnboundLocalError',
    'UnicodeDecodeError',
    'UnicodeEncodeError',
    'UnicodeError',
    'UnicodeTranslateError',
    'UnicodeWarning',
    'UserWarning',
    'ValueError',
    'Warning',
    'ZeroDivisionError',
    '_',
    '__builtins__',
    '__debug__',
    '__doc__',
    '__import__',
    '__name__',
    '__package__',
    'abs',
    'all',
    'any',
    'apply',
    'basestring',
    'bin',
    'bool',
    'buffer',
    'bytearray',
    'bytes',
    'callable',
    'chr',
    'classmethod',
    'cmp',
    'coerce',
    'compile',
    'complex',
    'copyright',
    'credits',
    'delattr',
    'dict',
    'dir',
    'divmod',
    'enumerate',
    'eval',
    'execfile',
    'exit',
    'file',
    'filter',
    'float',
    'format',
    'frozenset',
    'getattr',
    'globals',
    'hasattr',
    'hash',
    'help',
    'hex',
    'id',
    'input',
    'int',
    'intern',
    'isinstance',
    'issubclass',
    'iter',
    'len',
    'license',
    'list',
    'locals',
    'long',
    'map',
    'max',
    'min',
    'next',
    'object',
    'oct',
    'open',
    'ord',
    'pow',
    'print',
    'property',
    'quit',
    'range',
    'raw_input',
    'reduce',
    'reload',
    'repr',
    'reversed',
    'round',
    'set',
    'setattr',
    'slice',
    'sorted',
    'staticmethod',
    'str',
    'sum',
    'super',
    'tuple',
    'type',
    'unichr',
    'unicode',
    'vars',
    'xrange',
    'zip',
].__iter__():
    if JS("""typeof g$[@{{name}}.__s] != "undefined" """):
        __all__.append(name)
__nondynamic_modules__ = {}

debugger()
JS("""
@{{sys}} = $pyjs.loaded_modules['sys'];
@{{imp}} = $pyjs.loaded_modules['imp'];
@{{imp}}['$dict']['sys'] = @{{sys}};
@{{sys}}['$dict']['modules'] = $new(@{{dict}}, [[@{{__name__}}, m$]]);
@{{_builtin_object_}} = {};
for (var i = 0; i <  @{{__all__}}.__array.length; i++) {
    var name = @{{__all__}}.__array[i].valueOf();
    @{{_builtin_object_}}[name] = g$[name];
}
""")
non_reloadable_module_names = ['__builtin__', 'sys', 'exceptions', '__main__']
# Import the rest of the builtin modules
for name in ['sys', 'imp', 'dynamic']:
    # Get the module from $pyjs.loaded_modules
    # and create / update the global for this module g$[@{{name}}.valueOf()]
    # and store this in sys.module
    JS("""\
    @{{m}} = $pyjs.loaded_modules[@{{name}}.valueOf()];
    @{{m}}.$module_init();
    """)
    sys.modules[name] = m

import sys # needed for debug option
import imp
import dynamic # needed for ___import___

