def __next__(self): if hslowlevel.from_haskell_Bool(hslowlevel.apply(hs_null, self.cur)): raise StopIteration else: (this, self.cur) = ( hslowlevel.apply(hs_head, self.cur), hslowlevel.apply(hs_tail, self.cur)) return hyphen.marshall_obj_to_py.hs_to_py(this)
def __next__(self): if hslowlevel.from_haskell_Bool(hslowlevel.apply(hs_null, self.cur)): raise StopIteration else: (this, self.cur) = ( hslowlevel.apply(hs_head, self.cur), hslowlevel.apply(hs_tail, self.cur)) return hyphen.marshall_obj_to_py.hs_to_py(this)
def break_haskell_tuple(tuple_, treat_nontuple_as_lenth_1_tuple=False): """If tuple_ is an HsObj representing a Haskell tuple object (o1, o2, ..., on) then we return a Python tuple (x1, ..., xn) where x1 is an HsObj wrapping x1 and so on. >>> (hs_zero, hs_one, hs_two) = map(hslowlevel.to_haskell_Integer, (0, 1, 2)) >>> my_triple = hslowlevel.apply(hsprimitives['(,,)'], hs_zero, hs_one, hs_two) >>> my_triple # doctest: +ELLIPSIS <hsobjraw.HsObjRaw object at ...> >>> hslowlevel.from_haskell_String(hslowlevel.apply(hs_show, my_triple)) '(0,1,2)' >>> break_haskell_tuple(my_triple) # doctest: +ELLIPSIS (<hsobjraw.HsObjRaw object at ...>, <hsobjraw.HsObjRaw object at ...>, <hsobjraw.HsObjRaw object at ...>) >>> (x1, x2, x3) = break_haskell_tuple(my_triple) >>> [hslowlevel.from_haskell_String(hslowlevel.apply(hs_show, x)) for x in (x1, x2, x3)] ['0', '1', '2'] """ try: tlen = hs_tupletyc_lengths[tuple_.hstype.head_ll] except KeyError as e: if treat_nontuple_as_lenth_1_tuple: return (tuple_, ) raise TypeError( 'marshall_tuple: tuple input not recognized as being of a tuple ' 'type. (NB: we only support tuples of length <= 14.)') from e build = [] for i in range(tlen - 1): build.append(hslowlevel.apply(tuple_head[tlen - i], tuple_)) tuple_ = hslowlevel.apply(tuple_tail[tlen - i], tuple_) build.append(tuple_) return tuple(build)
def map_lookup(map_obj, key): """Given a Haskell Map object and a key, return the associated value if there is one; otherwise raise KeyError.""" result = applyFromPyArgs(hs_mapLookup, key, map_obj) if hslowlevel.from_haskell_Bool(hslowlevel.apply(hs_isJust, result)): return marshall_obj_to_py.hs_to_py(hslowlevel.apply(hs_fromJust, result)) else: raise KeyError(key)
def map_lookup(map_obj, key): """Given a Haskell Map object and a key, return the associated value if there is one; otherwise raise KeyError.""" result = applyFromPyArgs(hs_mapLookup, key, map_obj) if hslowlevel.from_haskell_Bool(hslowlevel.apply(hs_isJust, result)): return marshall_obj_to_py.hs_to_py(hslowlevel.apply(hs_fromJust, result)) else: raise KeyError(key)
def __repr__(self): try: foo = hslowlevel.apply(hs_show, self) shown = ', containing %r' % ( hslowlevel.from_haskell_String(hslowlevel.apply(hs_show, self)),) except: shown = '' return '<%s.%s object of Haskell type %s%s>' % ( type(self).__module__, type(self).__name__, self.hstype.name, shown)
def __repr__(self): try: foo = hslowlevel.apply(hs_show, self) shown = ', containing %r' % (hslowlevel.from_haskell_String( hslowlevel.apply(hs_show, self)), ) except: shown = '' return '<%s.%s object of Haskell type %s%s>' % (type( self).__module__, type(self).__name__, self.hstype.name, shown)
def interpret(cls, obj): assert obj.hstype.head_ll == cls.hs_tycon if len(obj.hstype.fvs) == 0: for co_dacon, resulting_class in ways_to_interpret: if not hslowlevel.from_haskell_Bool( hslowlevel.apply(hs_null, hslowlevel.apply(co_dacon, obj))): return hslowlevel.HsObjRaw.__new__(resulting_class, obj) return hslowlevel.HsObjRaw.__new__(cls, obj)
def interpret(cls, obj): assert obj.hstype.head_ll == cls.hs_tycon if len(obj.hstype.fvs) == 0: for co_dacon, resulting_class in ways_to_interpret: if not hslowlevel.from_haskell_Bool( hslowlevel.apply( hs_null, hslowlevel.apply(co_dacon, obj))): return hslowlevel.HsObjRaw.__new__(resulting_class, obj) return hslowlevel.HsObjRaw.__new__(cls, obj)
def _components(self): try: # We memoize the result in _components_store for speed efficiency return self._components_store except AttributeError: self._components_store = tuple(map( marshall_obj_to_py.hs_to_py, break_haskell_tuple( hslowlevel.apply(hs_head, hslowlevel.apply( co_dacon, self)), treat_nontuple_as_lenth_1_tuple=True))) return self._components_store
def _components(self): try: # We memoize the result in _components_store for speed efficiency return self._components_store except AttributeError: self._components_store = tuple(map( marshall_obj_to_py.hs_to_py, break_haskell_tuple( hslowlevel.apply(hs_head, hslowlevel.apply( co_dacon, self)), treat_nontuple_as_lenth_1_tuple=True))) return self._components_store
def applyFromPyArgs(fn, *args): """Given """ fn_type = fn.hstype arg_types, return_type = break_hs_fn_type(fn_type, len(args)) if len(arg_types) < len(args): raise TypeError( "Haskell object %s has been applied to %d arguments, but its type %s " "supports at most %d." % (fn, len(args), fn.hstype, len(arg_types))) assert len(arg_types) == len(args) fv_src = enumerate_fresh_vars_outside(fn_type.fvs) refined_arg_types = tuple([ marshall_obj_to_hs.pyobj_hstype_hint(args[i], arg_types[i], fv_src) for i in range(len(args)) ]) # This narrowing operation will allow type information learned # from one variable to be propagated to other variables and used # to help guide their transformation from python to haskell fn_ = fn.narrow_type(make_hs_fn_type(refined_arg_types, return_type)) arg_types_, _ = break_hs_fn_type(fn_.hstype, len(args)) return hslowlevel.apply( fn, *[ marshall_obj_to_hs.py_to_hs(args[i], arg_types_[i]) for i in range(len(args)) ])
def to_haskell_Map(obj, hstype): assert hstype.head_ll == hs_Map try: my_iter = iter(obj.items()) except: my_iter = ((k, obj[k]) for k in obj) return hslowlevel.apply( hs_mkMap, to_haskell_List(my_iter, hs_List(make_hs_tuple_type(*hstype.tail))))
def __eq__(self, other): if type(self) != type(other) or self.hstype != other.hstype: return False try: hs_eq_ = hs_eq.narrow_type(make_hs_fn_type( (self.hstype, self.hstype), hslowlevel.hstype_Bool)) except Exception: return False return hslowlevel.from_haskell_Bool(hslowlevel.apply(hs_eq_, self, other))
def to_haskell_Map(obj, hstype): assert hstype.head_ll == hs_Map try: my_iter = iter(obj.items()) except: my_iter = ((k, obj[k]) for k in obj) return hslowlevel.apply( hs_mkMap, to_haskell_List(my_iter, hs_List(make_hs_tuple_type(*hstype.tail))))
def __lt__(self, other): if type(self) != type(other) or self.hstype != other.hstype: return (type(self), self.hstype) < (type(other), other.hstype) try: hs_lt_ = hs_lt.narrow_type(make_hs_fn_type( (self.hstype, self.hstype), hslowlevel.hstype_Bool)) except Exception as e: raise ValueError( "Incomparable Haskell object of type %s" % self.hstype.name) from e return hslowlevel.from_haskell_Int(hslowlevel.apply(hs_lt_, self, other))
def __eq__(self, other): if type(self) != type(other) or self.hstype != other.hstype: return False try: hs_eq_ = hs_eq.narrow_type( make_hs_fn_type((self.hstype, self.hstype), hslowlevel.hstype_Bool)) except Exception: return False return hslowlevel.from_haskell_Bool( hslowlevel.apply(hs_eq_, self, other))
def to_haskell_List(obj, hstype): # If obj is an iterable whose elements can be converted to Haskell # objects of type X, then we can convert obj to be a Haskell # object of type [X]; this is most commonly used when in fact obj # is a python list. assert hstype.head_ll == hs_List elemType, = hstype.tail parts = [py_to_hs(elem, elemType) for elem in obj] hslist = hs_emptyList.narrow_type(hstype) for elem in reversed(parts): hslist = hslowlevel.apply(hs_cons, elem, hslist) return hslist
def to_haskell_List(obj, hstype): # If obj is an iterable whose elements can be converted to Haskell # objects of type X, then we can convert obj to be a Haskell # object of type [X]; this is most commonly used when in fact obj # is a python list. assert hstype.head_ll == hs_List elemType, = hstype.tail parts = [py_to_hs(elem, elemType) for elem in obj] hslist = hs_emptyList.narrow_type(hstype) for elem in reversed(parts): hslist = hslowlevel.apply(hs_cons, elem, hslist) return hslist
def __lt__(self, other): if type(self) != type(other) or self.hstype != other.hstype: return (type(self), self.hstype) < (type(other), other.hstype) try: hs_lt_ = hs_lt.narrow_type( make_hs_fn_type((self.hstype, self.hstype), hslowlevel.hstype_Bool)) except Exception as e: raise ValueError("Incomparable Haskell object of type %s" % self.hstype.name) from e return hslowlevel.from_haskell_Int( hslowlevel.apply(hs_lt_, self, other))
def to_haskell_Tuple(obj, hstype): assert hstype.head_ll in hs_tupletycs as_pytup = tuple(obj) if len(as_pytup) == 1: raise ValueError("No length 1 tuples in Haskell.") if len(as_pytup) > 14: raise ValueError("Converting tuples of length > 14 to Haskell not supported.") if len(as_pytup) != len(hstype.tail): raise ValueError( "Trying to convert python object %s of length %d to Haskell tuple " "of type %s with length %d" % (obj, len(as_pytup), hstype, len(hstype.tail))) parts = [py_to_hs(*pair) for pair in zip(as_pytup, hstype.tail)] return hslowlevel.apply(hsprimitives['(' + ',' * (len(as_pytup) - 1) + ')'], *parts)
def to_haskell_Maybe(obj, hstype): # Our convention is if we are asked to convert a python object to # Maybe X for some X, then we convert None to Nothing and # otherwise convert any other value we see to a Haskell object obj # of type X, then return Just obj. This convention is useful in # many ways, but dealing with Maybe (Maybe X) will give bad # results! (In this case, the user is recommended not to marshall # directly to Haskell Maybe (Maybe X) objects but to build them up # explicitly using Just and Nothing.) assert hstype.head_ll == hs_Maybe justType, = hstype.tail if obj is None: return hs_Nothing else: return hslowlevel.apply(hs_mkJust, py_to_hs(obj, justType))
def to_haskell_Maybe(obj, hstype): # Our convention is if we are asked to convert a python object to # Maybe X for some X, then we convert None to Nothing and # otherwise convert any other value we see to a Haskell object obj # of type X, then return Just obj. This convention is useful in # many ways, but dealing with Maybe (Maybe X) will give bad # results! (In this case, the user is recommended not to marshall # directly to Haskell Maybe (Maybe X) objects but to build them up # explicitly using Just and Nothing.) assert hstype.head_ll == hs_Maybe justType, = hstype.tail if obj is None: return hs_Nothing else: return hslowlevel.apply(hs_mkJust, py_to_hs(obj, justType))
def to_haskell_Tuple(obj, hstype): assert hstype.head_ll in hs_tupletycs as_pytup = tuple(obj) if len(as_pytup) == 1: raise ValueError("No length 1 tuples in Haskell.") if len(as_pytup) > 14: raise ValueError( "Converting tuples of length > 14 to Haskell not supported.") if len(as_pytup) != len(hstype.tail): raise ValueError( "Trying to convert python object %s of length %d to Haskell tuple " "of type %s with length %d" % (obj, len(as_pytup), hstype, len(hstype.tail))) parts = [py_to_hs(*pair) for pair in zip(as_pytup, hstype.tail)] return hslowlevel.apply( hsprimitives['(' + ',' * (len(as_pytup) - 1) + ')'], *parts)
def applyFromPyArgs(fn, *args): """Given """ fn_type = fn.hstype arg_types, return_type = break_hs_fn_type(fn_type, len(args)) if len(arg_types) < len(args): raise TypeError( "Haskell object %s has been applied to %d arguments, but its type %s " "supports at most %d." % (fn, len(args), fn.hstype, len(arg_types))) assert len(arg_types) == len(args) fv_src = enumerate_fresh_vars_outside(fn_type.fvs) refined_arg_types = tuple([ marshall_obj_to_hs.pyobj_hstype_hint(args[i], arg_types[i], fv_src) for i in range(len(args))]) # This narrowing operation will allow type information learned # from one variable to be propagated to other variables and used # to help guide their transformation from python to haskell fn_ = fn.narrow_type(make_hs_fn_type(refined_arg_types, return_type)) arg_types_, _ = break_hs_fn_type(fn_.hstype, len(args)) return hslowlevel.apply(fn, *[ marshall_obj_to_hs.py_to_hs(args[i], arg_types_[i]) for i in range(len(args))])
def to_haskell_Complex(obj, hstype): assert hstype.head_ll == hs_Complex partsType, = hstype.tail re = py_to_hs(obj.real, partsType) im = py_to_hs(obj.imag, partsType) return hslowlevel.apply(hs_mkComplex, re, im)
## The first kind of hook affects the type we build for a ## tycon. Recall that the Tycon object is the low-level bridge's ## representation of Haskell type constructors. The hook repository is ## a dictionary mapping TyCons to /customization dictionaries/. The ## customization dictionary consists of a series of modifications we ## will make to the type as we build it. Most of these are just (key, ## value) pairs that we want to insert into the class's dictioary; ## there are a couple of specials. First, if we have a key-value pair ## ("NAME", foo) then we set the name of the class to be foo. Second, ## if we have a key-value pair ("BASES", foo) then we use foo as the ## bases of the new class (it should be a tuple). tycon_specials = { hs_List : { "__iter__" : iterate_hslist, "__bool__" : member_from_unary_hsfn(hslowlevel.apply( hs_compose, hs_not, hs_null)) }, hs_Map : { "__getitem__" : map_lookup, "__iter__" : iterate_hsmap, "__len__" : member_from_unary_hsfn(hs_sizeOfMap), "BASES" : (collections.Mapping,), }, hs_Set : { "__contains__" : set_member, "__iter__" : iterate_hsset, "__len__" : member_from_unary_hsfn(hs_sizeOfSet), "BASES" : (collections.Set,), }, hs_Func : { "__call__" : apply_marshalled,
def to_haskell_Set(obj, hstype): assert hstype.head_ll == hs_Set elemType, = hstype.tail return hslowlevel.apply(hs_mkSet, to_haskell_List(obj, hs_List(elemType)))
def iterate_hsmap(the_map): """Given a HsObjRaw which represents a Haskell map, compute a python-iterator-protocol-compliant iterator which iterates through the keys of the map (as happens when you iterate through a python dict).""" return HsIterator(hslowlevel.apply(hs_mapKeys, the_map))
def iterate_hsset(the_set): """Given a HsObjRaw which represents a Haskell set, compute a python-iterator-protocol-compliant iterator which iterates through the set.""" return HsIterator(hslowlevel.apply(hs_setElems, the_set))
def closure(obj): hs_re = hslowlevel.apply(hs_real, obj) hs_im = hslowlevel.apply(hs_imag, obj) return complex(h_part_converter(hs_re), h_part_converter(hs_im))
def closure(obj): hs_re = hslowlevel.apply(hs_real, obj) hs_im = hslowlevel.apply(hs_imag, obj) return complex(h_part_converter(hs_re), h_part_converter(hs_im))
def __hash__(self): try: return hslowlevel.from_haskell_Int(hslowlevel.apply(hs_hash, self)) except Exception as e: raise ValueError("Unhashable Haskell object of type %s" % self.hstype.name) from e
## The first kind of hook affects the type we build for a ## tycon. Recall that the Tycon object is the low-level bridge's ## representation of Haskell type constructors. The hook repository is ## a dictionary mapping TyCons to /customization dictionaries/. The ## customization dictionary consists of a series of modifications we ## will make to the type as we build it. Most of these are just (key, ## value) pairs that we want to insert into the class's dictioary; ## there are a couple of specials. First, if we have a key-value pair ## ("NAME", foo) then we set the name of the class to be foo. Second, ## if we have a key-value pair ("BASES", foo) then we use foo as the ## bases of the new class (it should be a tuple). tycon_specials = { hs_List : { "__iter__" : iterate_hslist, "__bool__" : member_from_unary_hsfn(hslowlevel.apply( hs_compose, hs_not, hs_null)) }, hs_Map : { "__getitem__" : map_lookup, "__iter__" : iterate_hsmap, "__len__" : member_from_unary_hsfn(hs_sizeOfMap), "BASES" : (collections.Mapping,), }, hs_Set : { "__contains__" : set_member, "__iter__" : iterate_hsset, "__len__" : member_from_unary_hsfn(hs_sizeOfSet), "BASES" : (collections.Set,), }, hs_Func : { "__call__" : apply_marshalled,
def fn_with_placeholder_name(self): return marshall_obj_to_py.hs_to_py(hslowlevel.apply(to_apply, self))
def iterate_hsmap(the_map): """Given a HsObjRaw which represents a Haskell map, compute a python-iterator-protocol-compliant iterator which iterates through the keys of the map (as happens when you iterate through a python dict).""" return HsIterator(hslowlevel.apply(hs_mapKeys, the_map))
def __hash__(self): try: return hslowlevel.from_haskell_Int(hslowlevel.apply(hs_hash, self)) except Exception as e: raise ValueError( "Unhashable Haskell object of type %s" % self.hstype.name) from e
def to_haskell_Complex(obj, hstype): assert hstype.head_ll == hs_Complex partsType, = hstype.tail re = py_to_hs(obj.real, partsType) im = py_to_hs(obj.imag, partsType) return hslowlevel.apply(hs_mkComplex, re, im)
def iterate_hsset(the_set): """Given a HsObjRaw which represents a Haskell set, compute a python-iterator-protocol-compliant iterator which iterates through the set.""" return HsIterator(hslowlevel.apply(hs_setElems, the_set))
def to_haskell_Set(obj, hstype): assert hstype.head_ll == hs_Set elemType, = hstype.tail return hslowlevel.apply(hs_mkSet, to_haskell_List(obj, hs_List(elemType)))
def fn_with_placeholder_name(self): return marshall_obj_to_py.hs_to_py(hslowlevel.apply(to_apply, self))