def generate_setter(cl: ClassIR, attr: str, rtype: RType, emitter: Emitter) -> None: emitter.emit_line('static int') emitter.emit_line('{}({} *self, PyObject *value, void *closure)'.format( setter_name(cl, attr, emitter.names), cl.struct_name(emitter.names))) emitter.emit_line('{') if rtype.is_refcounted: emit_undefined_check(rtype, emitter, attr, '!=') emitter.emit_dec_ref('self->{}'.format(attr), rtype) emitter.emit_line('}') emitter.emit_line('if (value != NULL) {') if rtype.is_unboxed: emitter.emit_unbox('value', 'tmp', rtype, custom_failure='return -1;', declare_dest=True) elif is_same_type(rtype, object_rprimitive): emitter.emit_line('PyObject *tmp = value;') else: emitter.emit_cast('value', 'tmp', rtype, declare_dest=True) emitter.emit_lines('if (!tmp)', ' return -1;') emitter.emit_inc_ref('tmp', rtype) emitter.emit_line('self->{} = tmp;'.format(attr)) emitter.emit_line('} else') emitter.emit_line(' self->{} = {};'.format( attr, emitter.c_undefined_value(rtype))) emitter.emit_line('return 0;') emitter.emit_line('}')
def generate_native_getters_and_setters(cl: ClassIR, emitter: Emitter) -> None: for attr, rtype in cl.attributes.items(): # Native getter emitter.emit_line('{}{}({} *self)'.format( emitter.ctype_spaced(rtype), native_getter_name(cl, attr, emitter.names), cl.struct_name(emitter.names))) emitter.emit_line('{') if rtype.is_refcounted: emit_undefined_check(rtype, emitter, attr, '==') emitter.emit_lines( 'PyErr_SetString(PyExc_AttributeError, "attribute {} of {} undefined");' .format(repr(attr), repr(cl.name)), '} else {') emitter.emit_inc_ref('self->{}'.format(attr), rtype) emitter.emit_line('}') emitter.emit_line('return self->{};'.format(attr)) emitter.emit_line('}') emitter.emit_line() # Native setter emitter.emit_line('bool {}({} *self, {}value)'.format( native_setter_name(cl, attr, emitter.names), cl.struct_name(emitter.names), emitter.ctype_spaced(rtype))) emitter.emit_line('{') if rtype.is_refcounted: emit_undefined_check(rtype, emitter, attr, '!=') emitter.emit_dec_ref('self->{}'.format(attr), rtype) emitter.emit_line('}') # This steal the reference to src, so we don't need to increment the arg emitter.emit_lines('self->{} = value;'.format(attr), 'return 1;', '}') emitter.emit_line()
def generate_native_getters_and_setters(cl: ClassIR, emitter: Emitter) -> None: for attr, rtype in cl.attributes: emitter.emit_line('{}{}({} *self)'.format(rtype.ctype_spaced, native_getter_name(cl.name, attr), cl.struct_name)) emitter.emit_line('{') if rtype.is_refcounted: emitter.emit_line('if (self->{} != {}) {{'.format(attr, rtype.c_undefined_value)) emitter.emit_inc_ref('self->{}'.format(attr), rtype) emitter.emit_line('}') emitter.emit_line('return self->{};'.format(attr)) emitter.emit_line('}') emitter.emit_line() emitter.emit_line('void {}({} *self, {}value)'.format(native_setter_name(cl.name, attr), cl.struct_name, rtype.ctype_spaced)) emitter.emit_line('{') if rtype.is_refcounted: emitter.emit_line('if (self->{} != {}) {{'.format(attr, rtype.c_undefined_value)) emitter.emit_dec_ref('self->{}'.format(attr), rtype) emitter.emit_line('}') emitter.emit_inc_ref('value'.format(attr), rtype) emitter.emit_line('self->{} = value;'.format(attr)) emitter.emit_line('}') emitter.emit_line()
def generate_hash_wrapper(cl: ClassIR, fn: FuncIR, emitter: Emitter) -> str: """Generates a wrapper for native __hash__ methods.""" name = '{}{}{}'.format(DUNDER_PREFIX, fn.name, cl.name_prefix(emitter.names)) emitter.emit_line( 'static Py_ssize_t {name}(PyObject *self) {{'.format(name=name)) emitter.emit_line('{}retval = {}{}(self);'.format( emitter.ctype_spaced(fn.ret_type), NATIVE_PREFIX, fn.cname(emitter.names))) emitter.emit_error_check('retval', fn.ret_type, 'return -1;') if is_int_rprimitive(fn.ret_type): emitter.emit_line('Py_ssize_t val = CPyTagged_AsLongLong(retval);') else: emitter.emit_line('Py_ssize_t val = PyLong_AsLongLong(retval);') emitter.emit_dec_ref('retval', fn.ret_type) emitter.emit_line('if (PyErr_Occurred()) return -1;') # We can't return -1 from a hash function.. emitter.emit_line('if (val == -1) return -2;') emitter.emit_line('return val;') emitter.emit_line('}') return name
def generate_native_getters_and_setters(cl: ClassIR, emitter: Emitter) -> None: for attr, rtype in cl.attributes.items(): # Native getter emitter.emit_line('{}{}({} *self)'.format(emitter.ctype_spaced(rtype), native_getter_name(cl, attr, emitter.names), cl.struct_name(emitter.names))) emitter.emit_line('{') if rtype.is_refcounted: emitter.emit_lines( 'if (self->{} == {}) {{'.format(attr, emitter.c_undefined_value(rtype)), 'PyErr_SetString(PyExc_AttributeError, "attribute {} of {} undefined");'.format( repr(attr), repr(cl.name)), '} else {') emitter.emit_inc_ref('self->{}'.format(attr), rtype) emitter.emit_line('}') emitter.emit_line('return self->{};'.format(attr)) emitter.emit_line('}') emitter.emit_line() # Native setter emitter.emit_line( 'bool {}({} *self, {}value)'.format(native_setter_name(cl, attr, emitter.names), cl.struct_name(emitter.names), emitter.ctype_spaced(rtype))) emitter.emit_line('{') if rtype.is_refcounted: emitter.emit_line('if (self->{} != {}) {{'.format(attr, emitter.c_undefined_value(rtype))) emitter.emit_dec_ref('self->{}'.format(attr), rtype) emitter.emit_line('}') emitter.emit_inc_ref('value'.format(attr), rtype) emitter.emit_lines('self->{} = value;'.format(attr), 'return 1;', '}') emitter.emit_line()
def generate_setter(cl: ClassIR, attr: str, rtype: RType, emitter: Emitter) -> None: emitter.emit_line('static int') emitter.emit_line('{}({} *self, PyObject *value, void *closure)'.format( setter_name(cl.name, attr), cl.struct_name)) emitter.emit_line('{') if rtype.is_refcounted: emitter.emit_line('if (self->{} != {}) {{'.format(attr, rtype.c_undefined_value)) emitter.emit_dec_ref('self->{}'.format(attr), rtype) emitter.emit_line('}') emitter.emit_line('if (value != NULL) {') if rtype.supports_unbox: emitter.emit_unbox('value', 'tmp', rtype, 'abort();',declare_dest=True) else: emitter.emit_cast('value', 'tmp', rtype, 'abort();',declare_dest=True) emitter.emit_inc_ref('tmp', rtype) emitter.emit_line('self->{} = tmp;'.format(attr)) emitter.emit_line('} else') emitter.emit_line(' self->{} = {};'.format(attr, rtype.c_undefined_value)) emitter.emit_line('return 0;') emitter.emit_line('}')