# ITHON START import typing as _INTERNAL_typing import types as _INTERNAL_types import inspect as _INTERNAL_inspect import sys as _INTERNAL_sys class _INTERNAL_Token: __slots__ = ('action',) def __init__(self, action): self.action = action def __rrshift__(self, lhs): return _INTERNAL_Operation(self.action, lhs) class _INTERNAL_Operation: __slots__ = ('action', 'lhs') def __init__(self, action, lhs): self.action = action self.lhs = lhs def __lshift__(self, rhs): return self.action(self.lhs, rhs) class _INTERNAL_LazyIterable: __slots__ = ('x','y') def __init__(self, x, y) -> None: self.x = iter(x) self.y = iter(y) def __iter__(self): yield from self.x yield from self.y def curry(f): def wrapper(*args, **kwds) -> _INTERNAL_typing.Any | _INTERNAL_typing.Callable: signature = _INTERNAL_inspect.signature(f) ba = signature.bind_partial(*args, **kwds) if len(ba.arguments) == len(signature.parameters): return f(*args, **kwds) else: def _partial(*other_args, **other_kwds): combined_args = args + other_args combined_kwargs = dict(**kwds, **other_kwds) return curry(f)(*combined_args, **combined_kwargs) return _partial return wrapper def _INTERNAL_add_fakeimport(name: str, code: str): # TODO: make this use sys.meta_path module = _INTERNAL_types.ModuleType(name) parent = '.'.join(name.split('.')[:-1]) if '.'.join(name.split('.')[:-1]) else name if not parent == name and parent not in _INTERNAL_sys.modules: _INTERNAL_sys.modules[parent] = _INTERNAL_types.ModuleType(parent) globals = {'__package__': parent} print(globals) module.__dict__.update(globals) exec(code, module.__dict__) _INTERNAL_sys.modules[name] = module _INTERNAL_add_fakeimport('sentinels', '''import sys as _sys from threading import Lock as _Lock __all__ = ['Sentinel'] # Design and implementation decisions: # # The first implementations created a dedicated class for each instance. # However, once it was decided to use Sentinel for type signatures, there # was no longer a need for a dedicated class for each sentinel value on order # to enable strict type signatures. Since class objects consume a relatively # large amount of memory, the implementation was changed to avoid this. # # With this change, the mechanism used for unpickling/copying objects needed # to be changed too, since we could no longer count on each dedicated class # simply returning its singleton instance as before. __reduce__ can return # a string, upon which an attribute with that name is looked up in the module # and returned. However, that would have meant that pickling/copying support # would depend on the "name" argument being exactly the name of the variable # used in the module, and simply wouldn't work for sentinels created in # functions/methods. Instead, a registry for sentinels was added, where all # sentinel objects are stored keyed by their name + module name. This is used # to look up existing sentinels both during normal object creation and during # copying/unpickling. class Sentinel: """Create a unique sentinel object. *name* should be the fully-qualified name of the variable to which the return value shall be assigned. *repr*, if supplied, will be used for the repr of the sentinel object. If not provided, "" will be used (with any leading class names removed). *module_name*, if supplied, will be used instead of inspecting the call stack to find the name of the module from which """ _name: str _repr: str _module_name: str def __new__( cls, name: str, repr: str | None = None, module_name: str | None = None, ): name = str(name) repr = str(repr) if repr else f'<{name.split(".")[-1]}>' if not module_name: parent_frame = _get_parent_frame() module_name = ( parent_frame.f_globals.get('__name__', '__main__') if parent_frame is not None else __name__ ) # Include the class's module and fully qualified name in the # registry key to support sub-classing. registry_key = _sys.intern( f'{cls.__module__}-{cls.__qualname__}-{module_name}-{name}' ) sentinel = _registry.get(registry_key, None) if sentinel is not None: return sentinel sentinel = super().__new__(cls) sentinel._name = name sentinel._repr = repr sentinel._module_name = module_name with _lock: return _registry.setdefault(registry_key, sentinel) def __repr__(self): return self._repr def __reduce__(self): return ( self.__class__, ( self._name, self._repr, self._module_name, ), ) _lock = _Lock() _registry: dict[str, Sentinel] = {} # The following implementation attempts to support Python # implementations which don't support sys._getframe(2), such as # Jython and IronPython. # # The version added to the stdlib may simply return sys._getframe(2), # without the fallbacks. # # For reference, see the implementation of namedtuple: # https://github.com/python/cpython/blob/67444902a0f10419a557d0a2d3b8675c31b075a9/Lib/collections/__init__.py#L503 def _get_parent_frame(): """Return the frame object for the caller's parent stack frame.""" try: # Two frames up = the parent of the function which called this. return _sys._getframe(2) except (AttributeError, ValueError): global _get_parent_frame def _get_parent_frame(): """Return the frame object for the caller's parent stack frame.""" try: raise Exception except Exception: try: return _sys.exc_info()[2].tb_frame.f_back.f_back except Exception: global _get_parent_frame def _get_parent_frame(): """Return the frame object for the caller's parent stack frame.""" return None return _get_parent_frame() return _get_parent_frame()''') _INTERNAL_lazymerge = _INTERNAL_Token(lambda lhs, rhs: _INTERNAL_LazyIterable(lhs, rhs)) _INTERNAL_lpipe = _INTERNAL_Token(lambda lhs, rhs: rhs(lhs)) _INTERNAL_rpipe = _INTERNAL_Token(lambda lhs, rhs: lhs(rhs)) _INTERNAL_lspipe = _INTERNAL_Token(lambda lhs, rhs: rhs(*lhs)) _INTERNAL_rspipe = _INTERNAL_Token(lambda lhs, rhs: lhs(*rhs)) _INTERNAL_nonereplace = _INTERNAL_Token(lambda lhs, rhs: lhs if lhs != None else rhs) _INTERNAL_lto = _INTERNAL_Token(lambda lhs, rhs: lhs(*rhs)) # If you write in other programming languages, this is very, very useful. null = None nil = None void = None # ITHON END def fibonacci(x: int) -> list[int]: start = [0,1] for i in range(1, x): start.append <| start[i] + start[i - 1] return start a = 12 |> fibonacci b = a :: a :: a :: a c = b :: b :: b :: b print <| [i for i in c] print <*| ('a', 'b', 'c') d = lambda x: x * 2 #d2 = λ x: x * 2 d3d = curry <| (lambda x, y: x**2 + y**2) print(d3d(2,4)) print(d3d(2)(4)) print(d3d(x=2)(y=4)) @curry def d3d2(x,y) = x**2 + y**2 print(d3d2(2,4)) print(d3d2(2)(4)) print(d3d2(x=2)(y=4)) a = 1 a++ a |> print ?? 11 |> print '''a''' /* very bad code that is commented out for a very good reason */ a++ /* something */ # something 64 # ITHON START 65 1 import 1 typing 1 as 1 _INTERNAL_typing 4 1 import 1 types 1 as 1 _INTERNAL_types 4 1 import 1 inspect 1 as 1 _INTERNAL_inspect 4 1 import 1 sys 1 as 1 _INTERNAL_sys 4 1 class 1 _INTERNAL_Token 55 : 4 5 1 __slots__ 55 = 55 ( 3 'action' 55 , 55 ) 4 65 1 def 1 __init__ 55 ( 1 self 55 , 1 action 55 ) 55 : 4 5 1 self 55 . 1 action 55 = 1 action 4 65 6 1 def 1 __rrshift__ 55 ( 1 self 55 , 1 lhs 55 ) 55 : 4 5 1 return 1 _INTERNAL_Operation 55 ( 1 self 55 . 1 action 55 , 1 lhs 55 ) 4 65 6 6 1 class 1 _INTERNAL_Operation 55 : 4 5 1 __slots__ 55 = 55 ( 3 'action' 55 , 3 'lhs' 55 ) 4 65 1 def 1 __init__ 55 ( 1 self 55 , 1 action 55 , 1 lhs 55 ) 55 : 4 5 1 self 55 . 1 action 55 = 1 action 4 1 self 55 . 1 lhs 55 = 1 lhs 4 65 6 1 def 1 __lshift__ 55 ( 1 self 55 , 1 rhs 55 ) 55 : 4 5 1 return 1 self 55 . 1 action 55 ( 1 self 55 . 1 lhs 55 , 1 rhs 55 ) 4 65 6 6 1 class 1 _INTERNAL_LazyIterable 55 : 4 5 1 __slots__ 55 = 55 ( 3 'x' 55 , 3 'y' 55 ) 4 1 def 1 __init__ 55 ( 1 self 55 , 1 x 55 , 1 y 55 ) 55 -> 1 None 55 : 4 5 1 self 55 . 1 x 55 = 1 iter 55 ( 1 x 55 ) 4 1 self 55 . 1 y 55 = 1 iter 55 ( 1 y 55 ) 4 6 1 def 1 __iter__ 55 ( 1 self 55 ) 55 : 4 5 1 yield 1 from 1 self 55 . 1 x 4 1 yield 1 from 1 self 55 . 1 y 4 65 6 6 1 def 1 curry 55 ( 1 f 55 ) 55 : 4 5 1 def 1 wrapper 55 ( 55 * 1 args 55 , 55 ** 1 kwds 55 ) 55 -> 1 _INTERNAL_typing 55 . 1 Any 55 | 1 _INTERNAL_typing 55 . 1 Callable 55 : 4 5 1 signature 55 = 1 _INTERNAL_inspect 55 . 1 signature 55 ( 1 f 55 ) 4 1 ba 55 = 1 signature 55 . 1 bind_partial 55 ( 55 * 1 args 55 , 55 ** 1 kwds 55 ) 4 1 if 1 len 55 ( 1 ba 55 . 1 arguments 55 ) 55 == 1 len 55 ( 1 signature 55 . 1 parameters 55 ) 55 : 4 5 1 return 1 f 55 ( 55 * 1 args 55 , 55 ** 1 kwds 55 ) 4 6 1 else 55 : 4 5 1 def 1 _partial 55 ( 55 * 1 other_args 55 , 55 ** 1 other_kwds 55 ) 55 : 4 5 1 combined_args 55 = 1 args 55 + 1 other_args 4 1 combined_kwargs 55 = 1 dict 55 ( 55 ** 1 kwds 55 , 55 ** 1 other_kwds 55 ) 4 1 return 1 curry 55 ( 1 f 55 ) 55 ( 55 * 1 combined_args 55 , 55 ** 1 combined_kwargs 55 ) 4 6 1 return 1 _partial 4 6 6 1 return 1 wrapper 4 65 6 1 def 1 _INTERNAL_add_fakeimport 55 ( 1 name 55 : 1 str 55 , 1 code 55 : 1 str 55 ) 55 : 64 # TODO: make this use sys.meta_path 4 5 1 module 55 = 1 _INTERNAL_types 55 . 1 ModuleType 55 ( 1 name 55 ) 4 1 parent 55 = 3 '.' 55 . 1 join 55 ( 1 name 55 . 1 split 55 ( 3 '.' 55 ) 55 [ 55 : 55 - 2 1 55 ] 55 ) 1 if 3 '.' 55 . 1 join 55 ( 1 name 55 . 1 split 55 ( 3 '.' 55 ) 55 [ 55 : 55 - 2 1 55 ] 55 ) 1 else 1 name 4 1 if 1 not 1 parent 55 == 1 name 1 and 1 parent 1 not 1 in 1 _INTERNAL_sys 55 . 1 modules 55 : 4 5 1 _INTERNAL_sys 55 . 1 modules 55 [ 1 parent 55 ] 55 = 1 _INTERNAL_types 55 . 1 ModuleType 55 ( 1 parent 55 ) 4 6 1 globals 55 = 55 { 3 '__package__' 55 : 1 parent 55 } 4 1 print 55 ( 1 globals 55 ) 4 1 module 55 . 1 __dict__ 55 . 1 update 55 ( 1 globals 55 ) 4 1 exec 55 ( 1 code 55 , 1 module 55 . 1 __dict__ 55 ) 4 1 _INTERNAL_sys 55 . 1 modules 55 [ 1 name 55 ] 55 = 1 module 4 65 6 1 _INTERNAL_add_fakeimport 55 ( 3 'sentinels' 55 , 3 '''import sys as _sys from threading import Lock as _Lock __all__ = ['Sentinel'] # Design and implementation decisions: # # The first implementations created a dedicated class for each instance. # However, once it was decided to use Sentinel for type signatures, there # was no longer a need for a dedicated class for each sentinel value on order # to enable strict type signatures. Since class objects consume a relatively # large amount of memory, the implementation was changed to avoid this. # # With this change, the mechanism used for unpickling/copying objects needed # to be changed too, since we could no longer count on each dedicated class # simply returning its singleton instance as before. __reduce__ can return # a string, upon which an attribute with that name is looked up in the module # and returned. However, that would have meant that pickling/copying support # would depend on the "name" argument being exactly the name of the variable # used in the module, and simply wouldn't work for sentinels created in # functions/methods. Instead, a registry for sentinels was added, where all # sentinel objects are stored keyed by their name + module name. This is used # to look up existing sentinels both during normal object creation and during # copying/unpickling. class Sentinel: """Create a unique sentinel object. *name* should be the fully-qualified name of the variable to which the return value shall be assigned. *repr*, if supplied, will be used for the repr of the sentinel object. If not provided, "" will be used (with any leading class names removed). *module_name*, if supplied, will be used instead of inspecting the call stack to find the name of the module from which """ _name: str _repr: str _module_name: str def __new__( cls, name: str, repr: str | None = None, module_name: str | None = None, ): name = str(name) repr = str(repr) if repr else f'<{name.split(".")[-1]}>' if not module_name: parent_frame = _get_parent_frame() module_name = ( parent_frame.f_globals.get('__name__', '__main__') if parent_frame is not None else __name__ ) # Include the class's module and fully qualified name in the # registry key to support sub-classing. registry_key = _sys.intern( f'{cls.__module__}-{cls.__qualname__}-{module_name}-{name}' ) sentinel = _registry.get(registry_key, None) if sentinel is not None: return sentinel sentinel = super().__new__(cls) sentinel._name = name sentinel._repr = repr sentinel._module_name = module_name with _lock: return _registry.setdefault(registry_key, sentinel) def __repr__(self): return self._repr def __reduce__(self): return ( self.__class__, ( self._name, self._repr, self._module_name, ), ) _lock = _Lock() _registry: dict[str, Sentinel] = {} # The following implementation attempts to support Python # implementations which don't support sys._getframe(2), such as # Jython and IronPython. # # The version added to the stdlib may simply return sys._getframe(2), # without the fallbacks. # # For reference, see the implementation of namedtuple: # https://github.com/python/cpython/blob/67444902a0f10419a557d0a2d3b8675c31b075a9/Lib/collections/__init__.py#L503 def _get_parent_frame(): """Return the frame object for the caller's parent stack frame.""" try: # Two frames up = the parent of the function which called this. return _sys._getframe(2) except (AttributeError, ValueError): global _get_parent_frame def _get_parent_frame(): """Return the frame object for the caller's parent stack frame.""" try: raise Exception except Exception: try: return _sys.exc_info()[2].tb_frame.f_back.f_back except Exception: global _get_parent_frame def _get_parent_frame(): """Return the frame object for the caller's parent stack frame.""" return None return _get_parent_frame() return _get_parent_frame()''' 55 ) 4 1 _INTERNAL_lazymerge 55 = 1 _INTERNAL_Token 55 ( 1 lambda 1 lhs 55 , 1 rhs 55 : 1 _INTERNAL_LazyIterable 55 ( 1 lhs 55 , 1 rhs 55 ) 55 ) 4 65 1 _INTERNAL_lpipe 55 = 1 _INTERNAL_Token 55 ( 1 lambda 1 lhs 55 , 1 rhs 55 : 1 rhs 55 ( 1 lhs 55 ) 55 ) 4 1 _INTERNAL_rpipe 55 = 1 _INTERNAL_Token 55 ( 1 lambda 1 lhs 55 , 1 rhs 55 : 1 lhs 55 ( 1 rhs 55 ) 55 ) 4 1 _INTERNAL_lspipe 55 = 1 _INTERNAL_Token 55 ( 1 lambda 1 lhs 55 , 1 rhs 55 : 1 rhs 55 ( 55 * 1 lhs 55 ) 55 ) 4 1 _INTERNAL_rspipe 55 = 1 _INTERNAL_Token 55 ( 1 lambda 1 lhs 55 , 1 rhs 55 : 1 lhs 55 ( 55 * 1 rhs 55 ) 55 ) 4 65 1 _INTERNAL_nonereplace 55 = 1 _INTERNAL_Token 55 ( 1 lambda 1 lhs 55 , 1 rhs 55 : 1 lhs 1 if 1 lhs 55 != 1 None 1 else 1 rhs 55 ) 4 65 1 _INTERNAL_lto 55 = 1 _INTERNAL_Token 55 ( 1 lambda 1 lhs 55 , 1 rhs 55 : 1 lhs 55 ( 55 * 1 rhs 55 ) 55 ) 4 65 64 # If you write in other programming languages, this is very, very useful. 65 1 null 55 = 1 None 4 1 nil 55 = 1 None 4 1 void 55 = 1 None 4 65 64 # ITHON END 65 1 def 1 fibonacci 55 ( 1 x 55 : 1 int 55 ) 55 -> 1 list 55 [ 1 int 55 ] 55 : 4 5 1 start 55 = 55 [ 2 0 55 , 2 1 55 ] 4 1 for 1 i 1 in 1 range 55 ( 2 1 55 , 1 x 55 ) 55 : 4 5 1 start 55 . 1 append 55 < 55 | 1 start 55 [ 1 i 55 ] 55 + 1 start 55 [ 1 i 55 - 2 1 55 ] 4 6 1 return 1 start 4 6 1 a 55 = 2 12 55 | 55 > 1 fibonacci 4 1 b 55 = 1 a 55 : 55 : 1 a 55 : 55 : 1 a 55 : 55 : 1 a 4 1 c 55 = 1 b 55 : 55 : 1 b 55 : 55 : 1 b 55 : 55 : 1 b 4 1 print 55 < 55 | 55 [ 1 i 1 for 1 i 1 in 1 c 55 ] 4 1 print 55 < 55 * 55 | 55 ( 3 'a' 55 , 3 'b' 55 , 3 'c' 55 ) 4 1 d 55 = 1 lambda 1 x 55 : 1 x 55 * 2 2 4 64 #d2 = λ x: x * 2 65 65 1 d3d 55 = 1 curry 55 < 55 | 55 ( 1 lambda 1 x 55 , 1 y 55 : 1 x 55 ** 2 2 55 + 1 y 55 ** 2 2 55 ) 4 1 print 55 ( 1 d3d 55 ( 2 2 55 , 2 4 55 ) 55 ) 4 1 print 55 ( 1 d3d 55 ( 2 2 55 ) 55 ( 2 4 55 ) 55 ) 4 1 print 55 ( 1 d3d 55 ( 1 x 55 = 2 2 55 ) 55 ( 1 y 55 = 2 4 55 ) 55 ) 4 55 @ 1 curry 4 1 def 1 d3d2 55 ( 1 x 55 , 1 y 55 ) 55 = 1 x 55 ** 2 2 55 + 1 y 55 ** 2 2 4 1 print 55 ( 1 d3d2 55 ( 2 2 55 , 2 4 55 ) 55 ) 4 1 print 55 ( 1 d3d2 55 ( 2 2 55 ) 55 ( 2 4 55 ) 55 ) 4 1 print 55 ( 1 d3d2 55 ( 1 x 55 = 2 2 55 ) 55 ( 1 y 55 = 2 4 55 ) 55 ) 4 65 1 a 55 = 2 1 4 1 a 55 + 55 + 4 1 a 55 | 55 > 1 print 55 ? 55 ? 2 11 55 | 55 > 1 print 4 3 '''a''' 4 55 / 55 * 4 1 very 1 bad 1 code 1 that 1 is 4 1 commented 1 out 1 for 1 a 1 very 4 1 good 1 reason 4 55 * 55 / 4 1 a 55 + 55 + 55 / 55 * 1 something 55 * 55 / 64 # something 4 0