"""generates code for binops in PyObject and for all "simple" ops in PyInstance"""

binops = \
	[('add', '+'), ('sub', '-'), ('mul', '*'), ('div', '/'),
	 ('mod', '%'), ('divmod', 'divmod'), ('pow', '**'), 
	 ('lshift', '<<'), ('rshift', '>>'), ('and', '&'), ('or', '|'), ('xor', '^')]

template = """\
    /**
     * Equivalent to the standard Python __%(name)s__ method
     * @param     other the object to perform this binary operation with
     *            (the right-hand operand).
     * @return    the result of the %(name)s, or null if this operation
     *            is not defined
     **/
    public PyObject __%(name)s__(PyObject other) { %(function)s }

    /**
     * Equivalent to the standard Python __r%(name)s__ method
     * @param     other the object to perform this binary operation with
     *            (the left-hand operand).
     * @return    the result of the %(name)s, or null if this operation
     *            is not defined.
     **/
    public PyObject __r%(name)s__(PyObject other) { %(rfunction)s }

    /**
     * Equivalent to the standard Python __i%(name)s__ method
     * @param     other the object to perform this binary operation with
     *            (the right-hand operand).
     * @return    the result of the %(name)s, or null if this operation
     *            is not defined
     **/
    public PyObject __i%(name)s__(PyObject other) { return _%(name)s(other); }

    /**
     * Implements the Python expression <code>this %(op)s other</code>
     * @param     other the object to perform this binary operation with.
     * @return    the result of the %(name)s.
     * @exception PyTypeError if this operation can't be performed
     *            with these operands.
     **/
    public final PyObject _%(name)s(PyObject o2) {
        PyObject x = __%(name)s__(o2);
        if (x != null)
            return x;
        x = o2.__r%(name)s__(this);
        if (x != null)
            return x;
        throw Py.TypeError(
                 "__%(name)s__ nor __r%(name)s__ defined for these operands");
    }

"""

fp = open('binops.txt', 'w')

fp.write('    // Generated by make_binops.py (Begin)\n\n')

for name, op in binops:
	rfunction = function = 'return null;'

	if name == 'pow':
		function = 'return __pow__(other, null);'
	
	fp.write(template % {'name':name, 'op':op, 'function':function, 'rfunction':rfunction})

fp.write('    // Generated by make_binops.py (End)\n\n')

fp.close()



fp = open('binopsi.txt', 'w')

fp.write('    // Generated by make_binops.py\n\n')

comment = """\
    /**
     * Implements the __%(name)s__ method by looking it up
     * in the instance's dictionary and calling it if it is found.
     **/
"""

template1 = comment + """\
    public %(ret)s __%(name)s__() {
        PyObject ret = invoke("__%(name)s__");
        if (ret instanceof %(ret)s)
            return (%(ret)s)ret;
        throw Py.TypeError("__%(name)s__() should return a %(retname)s");
    }

"""
template2 = comment + """\
    public PyObject __%(name)s__() {
        return invoke("__%(name)s__");
    }

"""

string = 'PyString', 'string'
ops = [('hex', string), ('oct', string), 
		('int', ('PyInteger', 'int')), ('float', ('PyFloat', 'float')), 
		('long', ('PyLong', 'long')), ('complex', ('PyComplex', 'complex')),
		('pos', None), ('neg', None), ('abs', None), ('invert', None)]
	
fp.write('    // Unary ops\n\n')	
for name, ret in ops:
	if ret is None:
		fp.write(template2 % {'name':name})
	else:
		ret, retname = ret
		fp.write(template1 % {'name':name, 'ret':ret, 'retname':retname})



template = comment + """\
    public PyObject __%(name)s__(PyObject o) {
        Object ctmp = __coerce_ex__(o);
        if (ctmp == null || ctmp == Py.None)
            return invoke_ex("__%(name)s__", o);
        else {
            PyObject o1 = ((PyObject[])ctmp)[0];
            PyObject o2 = ((PyObject[])ctmp)[1];
            if (this == o1) // Prevent recusion if __coerce__ return self
                return invoke_ex("__%(name)s__", o2);
            else
                return %(function)s;
        }
    }

"""


template2 = comment + """\
    public PyObject __%(name)s__(PyObject o) {
        PyObject ret = invoke_ex("__%(name)s__", o);
        if (ret != null)
            return ret;
        return super.__%(name)s__(o);
    }

"""

fp.write('    // Binary ops\n\n')
for name, op in binops:	
	fp.write(template % {'name':name, 'function':'o1._%s(o2)' % name })
	fp.write(template % {'name':'r'+name, 'function':'o2._%s(o1)' % name })
        if name != 'divmod':
		fp.write(template2 % {'name':'i'+name
})


fp.close()

