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: 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_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_setup_for_class(cl: ClassIR, func_name: str, defaults_fn: Optional[FuncIR], vtable_name: str, emitter: Emitter) -> None: """Generate a native function that allocates an instance of a class.""" emitter.emit_line('static PyObject *') emitter.emit_line('{}(void)'.format(func_name)) emitter.emit_line('{') emitter.emit_line('{} *self;'.format(cl.struct_name(emitter.names))) emitter.emit_line( 'self = ({struct} *){type_struct}->tp_alloc({type_struct}, 0);'.format( struct=cl.struct_name(emitter.names), type_struct=emitter.type_struct_name(cl))) emitter.emit_line('if (self == NULL)') emitter.emit_line(' return NULL;') emitter.emit_line('self->vtable = {};'.format(vtable_name)) for base in reversed(cl.base_mro): for attr, rtype in base.attributes.items(): emitter.emit_line('self->{} = {};'.format( attr, emitter.c_undefined_value(rtype))) # Initialize attributes to default values, if necessary if defaults_fn is not None: emitter.emit_lines( 'if ({}{}((PyObject *)self) == 0) {{'.format( NATIVE_PREFIX, defaults_fn.cname(emitter.names)), 'Py_DECREF(self);', 'return NULL;', '}') emitter.emit_line('return (PyObject *)self;') emitter.emit_line('}')
def emit_undefined_check(rtype: RType, emitter: Emitter, attr: str, compare: str) -> None: if isinstance(rtype, RTuple): attr_expr = 'self->{}'.format(attr) emitter.emit_line( 'if ({}) {{'.format( emitter.tuple_undefined_check_cond( rtype, attr_expr, emitter.c_undefined_value, compare))) else: emitter.emit_line( 'if (self->{} {} {}) {{'.format(attr, compare, emitter.c_undefined_value(rtype)))
def final_definition( self, module: str, name: str, typ: RType, emitter: Emitter) -> str: static_name = emitter.static_name(name, module) # Here we rely on the fact that undefined value and error value are always the same if isinstance(typ, RTuple): # We need to inline because initializer must be static undefined = '{{ {} }}'.format(''.join(emitter.tuple_undefined_value_helper(typ))) else: undefined = emitter.c_undefined_value(typ) return '{}{} = {};'.format(emitter.ctype_spaced(typ), static_name, undefined)
def define_finals(self, final_names: Iterable[Tuple[str, RType]], emitter: Emitter) -> None: for name, typ in final_names: static_name = emitter.static_name(name, 'final') # Here we rely on the fact that undefined value and error value are always the same if isinstance(typ, RTuple): # We need to inline because initializer must be static undefined = '{{ {} }}'.format(''.join(emitter.tuple_undefined_value_helper(typ))) else: undefined = emitter.c_undefined_value(typ) emitter.emit_line('{}{} = {};'.format(emitter.ctype_spaced(typ), static_name, undefined))
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_getter(cl: ClassIR, attr: str, rtype: RType, emitter: Emitter) -> None: emitter.emit_line('static PyObject *') emitter.emit_line('{}({} *self, void *closure)'.format(getter_name(cl, attr, emitter.names), cl.struct_name(emitter.names))) emitter.emit_line('{') emitter.emit_line('if (self->{} == {}) {{'.format(attr, emitter.c_undefined_value(rtype))) emitter.emit_line('PyErr_SetString(PyExc_AttributeError,') emitter.emit_line(' "attribute {} of {} undefined");'.format(repr(attr), repr(cl.name))) emitter.emit_line('return NULL;') emitter.emit_line('}') emitter.emit_inc_ref('self->{}'.format(attr), rtype) emitter.emit_box('self->{}'.format(attr), 'retval', rtype, declare_dest=True) emitter.emit_line('return retval;') emitter.emit_line('}')
def generate_setup_for_class(cl: ClassIR, func_name: str, vtable_name: str, emitter: Emitter) -> None: """Generate a native function that allocates an instance of a class.""" emitter.emit_line('static PyObject *') emitter.emit_line('{}(void)'.format(func_name)) emitter.emit_line('{') emitter.emit_line('{} *self;'.format(cl.struct_name(emitter.names))) emitter.emit_line('self = ({struct} *){type_struct}.tp_alloc(&{type_struct}, 0);'.format( struct=cl.struct_name(emitter.names), type_struct=emitter.type_struct_name(cl))) emitter.emit_line('if (self == NULL)') emitter.emit_line(' return NULL;') emitter.emit_line('self->vtable = {};'.format(vtable_name)) for base in reversed(cl.base_mro): for attr, rtype in base.attributes.items(): emitter.emit_line('self->{} = {};'.format(attr, emitter.c_undefined_value(rtype))) emitter.emit_line('return (PyObject *)self;') emitter.emit_line('}')